PHD*_*PHD 5 c++ templates language-lawyer c++-concepts c++20
(最初与此问题分开。)
在下面的代码片段中,
#include <concepts>
template<
typename T,
typename value_type = typename T::value_type
>
concept check_type = std::default_initializable<T>;
struct Foo {};
template<check_type T>
void func(T t) {}
int main()
{
Foo foo;
func(foo);
}
Run Code Online (Sandbox Code Playgroud)
struct Foo不包含类型别名,value_type但它在 GCC 编译时没有错误。
查看在编译器资源管理器上测试的结果。
但是,使用 Clang 时,它会报告以下错误消息:
? clang++ -std=c++20 asdf.cpp
asdf.cpp:17:5: error: no matching function for call to 'func'
func(foo);
^~~~
asdf.cpp:12:6: note: candidate template ignored: constraints not satisfied [with T = Foo]
void func(T t) {}
^
asdf.cpp:5:39: note: because substituted constraint expression is ill-formed: no type named 'value_type' in 'Foo'
typename value_type = typename T::value_type
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
另请参阅在编译器资源管理器上测试的结果。
这是一个错误吗?
GCC 在目前的措辞下是正确的。
根据[temp.deduct]/5 ,对函数模板的关联约束进行满意度检查:
如果函数模板具有关联的约束 ([temp.constr.decl]),则检查这些约束是否满足 ([temp.constr.constr])。
[temp.constr.decl]/3.2指定关联约束基于范式:
声明的关联约束定义如下:
- ...
- 否则,如果存在单个引入的 约束表达式,则关联的约束是该表达式的正常形式。
由于check_type是一个概念,因此它对于规范化 ( [temp.constr.normal]/1.4 ) 是透明的,并且由于 的第二个模板参数check_type未在其定义中使用,因此该参数不会出现在约束表达式的规范形式中。因此,有效性(或缺乏有效性)T::value_type对满意度检查没有影响。
如果你想要检查 的概念value_type,直接检查 会更具表现力(更不用说正确了)value_type:
template <typename T>
concept check_type = std::default_initializable<T> && requires { typename T::value_type; };
Run Code Online (Sandbox Code Playgroud)