Consider the following class A that defines a template inner class B:
struct A {
template<class = int>
struct B { };
};
We can use the following expression to initialize inner B, where typename is optional: (Godbolt)
int main() {
A::template B<>();
typename A::template B<>();
}
I want to use concept to detect whether a type has a template inner class B:
template<class T>
concept C = requires {
typename T::template B<>();
};
static_assert(C<A>);
But only Clang accepted the above code, GCC and MSVC rejected it due to syntax error (Godbolt):
<source>:8:27: error: expected ';' before '(' token
8 | typename T::template B<>();
| ^
| ;
And if I remove the typename in the require clause:
template<class T>
concept C = requires {
T::template B<>();
};
MSVC accepted it, but Clang and GCC will produce static assertion failed since they think the expression is not well-formed (Godbolt):
<source>:11:15: note: because 'A' does not satisfy 'C'
static_assert(C<A>);
^
<source>:8:15: note: because 'T::template B<>()' would be invalid: 'A::B' instantiated to a class template, not a function template
T::template B<>();
^
Which compiler should I trust?