【发布时间】:2022-01-21 10:48:29
【问题描述】:
考虑以下定义模板内部类B的类A:
struct A {
template<class = int>
struct B { };
};
我们可以使用下面的表达式来初始化内部B,其中typename是可选的:(Godbolt)
int main() {
A::template B<>();
typename A::template B<>();
}
我想用concept来检测一个类型是否有模板内部类B:
template<class T>
concept C = requires {
typename T::template B<>();
};
static_assert(C<A>);
但是只有 Clang 接受了上面的代码,GCC 和 MSVC 由于语法错误拒绝了它(Godbolt):
<source>:8:27: error: expected ';' before '(' token
8 | typename T::template B<>();
| ^
| ;
如果我删除require 子句中的typename:
template<class T>
concept C = requires {
T::template B<>();
};
MSVC 接受了它,但 Clang 和 GCC 会生成 static assertion failed,因为他们认为表达式格式不正确 (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<>();
^
我应该信任哪个编译器?
【问题讨论】:
-
template在A::template中是不必要的,因为A不依赖。您可以从要求中省略(),至少使它们在语法上有效。
标签: c++ templates language-lawyer c++20 c++-concepts