嵌套的依赖名称不在模板中评估概念

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)

另请参阅在编译器资源管理器上测试结果

这是一个错误吗?

T.C*_*.C. 3

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)