1

我正在用 c++17 编译以下代码:

#include <iostream>

struct A {
    void barA() const {std::cout << "barA\n";}
};

struct B {
    void barB() const {std::cout << "barB\n";}
};

template<typename T>
constexpr bool isBaseA() {
    return std::is_base_of<A, T>::value;
}

template<typename T>
constexpr bool isBaseB() {
    return std::is_base_of<B, T>::value;
}

template<typename... Args>
class K : public Args... {
public:
void foo() {
    using MyK = K<Args...>;
    
    if constexpr(isBaseA<MyK>()) {
        using X = typename MyK::A;
        X::barA();
    }
    if constexpr(isBaseB<MyK>()) {
        using X = typename MyK::B;
        X::barB();
    }
}
};

int main()
{
    K<A, B> k;
    k.foo();
    return 0;
}

演示

使用 MSVC 2019(版本 16.8.30804.86,它应该是最后一个可用的版本)构建时,我在该行遇到了一个奇怪的 C2143 错误

void foo() {

完整的 C2143 错误是:

<source>(24): error C2143: syntax error: missing ')' before ';'
<source>(24): note: while compiling class template member function 'void K<A,B>::foo(void)'
<source>(41): note: see reference to function template instantiation 'void K<A,B>::foo(void)' being compiled
<source>(40): note: see reference to class template instantiation 'K<A,B>' being compiled
<source>(24): error C2143: syntax error: missing ';' before ')'
<source>(24): error C2059: syntax error: ')'

我注意到:

  • 如果我评论if constexpr函数的第二个块foo,错误就会消失;
  • 如果我没有定义 alias using MyK = K<Args...>;,错误就会消失。

该代码在 gcc 和 clang 上都可以正常工作。这只是一个 MSVC 错误,还是我在代码中的某处破坏了 c++17 标准?

4

1 回答 1

1

看起来像一个解析器错误,因为添加括号可以避免错误。在这种情况下,添加括号应该完全没有效果:

template<typename... Args>
class K : public Args... {
public:
void foo() {
    using MyK = K<Args...>;
    
    // extra parentheses to overcome MSVC error
    if constexpr((isBaseA<MyK>())) {
        using X = typename MyK::A;
        X::barA();
    }
    if constexpr(isBaseB<MyK>()) {
        using X = typename MyK::B;
        X::barB();
    }
}
};

编译器资源管理器工作示例

于 2022-01-25T14:51:39.410 回答