I am compiling the following code with 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;
}
When building with MSVC 2019 (version 16.8.30804.86, it should be the last available one), I am getting a weird C2143 error at the line
void foo() {
The complete C2143 error is :
<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: ')'
I noticed that:
if constexpr
block of the function foo
, the error goes away;using MyK = K<Args...>;
, the error goes away.The code works fine both on gcc and clang. Is this just a MSVC bug, or am I breaking the c++17 standard somewhere in the code?
Looks like a parser bug, as adding parentheses avoids the error. Adding parentheses should have no effect at all in this context:
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();
}
}
};