C++ 嵌套的从属名称不会在概念的模板中求值

C++ 嵌套的从属名称不会在概念的模板中求值,c++,templates,language-lawyer,c++20,c++-concepts,C++,Templates,Language Lawyer,C++20,C++ Concepts,(最初与分离。) 在下面的代码段中 #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) {}

(最初与分离。)

在下面的代码段中

#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);
}
另请参阅


这是一个错误吗?

根据当前的措辞,GCC是正确的

根据,对功能模板的相关约束进行满意度检查:

如果函数模板具有相关约束([temp.Const.decl]),则会检查这些约束是否满足([temp.Const.Const])

指定关联的约束基于法线形式:

声明的关联约束定义如下:

  • 否则,如果引入了单个 约束表达式,关联的约束是标准形式 那句话的意思
由于
check_type
是一个概念,它对规范化()是透明的,并且由于
check_type
的第二个模板参数未在其定义中使用,因此该参数不会以约束表达式的正常形式出现。因此,
T::value_type
的有效性(或缺乏有效性)对满意度检查没有影响

如果您想让概念检查
value\u type
,直接检查
value\u type
更具表现力(更不用说正确):

template <typename T>
concept check_type = std::default_initializable<T> && requires { typename T::value_type; };
模板
概念检查_type=std::default_initializable&&需要{typename T::value_type;};

这可能值得一次CWG问题。如果替换失败在约束表达式内。但就我所见,在约束自己的模板参数列表中没有提到任何关于替换失败的内容。我认为GCC无论如何都是错误的。Clang认为这并不令人满意。但是可以说这应该是一个硬错误,因为约束肯定可以在SFINAE中被重新写入not do SFINAE。@StoryTeller UnslanderMonica如果模板参数的约束产生false,那么给定您给出的链接,GCC应该会引发错误。不管怎样,我正在报告这个错误。@StoryTeller UnslanderMonica另外,什么是CWG?我搜索它,它看起来像是C++社区驱动的一个工作草案(共识)。你误解了。我共享的链接是关于表达式包含问题时的行为,而不是参数列表。就我所知,GCC在表达式中的行为是正确的(除非存在回归)。据我所知,本标准未涵盖您的示例。这就是为什么可能会向核心工作组(负责核心语言,作为ISO WG21的一部分)提出问题的原因。@StoryTeller UnslanderMonica该概念根本不使用
value\u type
,因此规范化后它不是参数映射的一部分。我认为GCC是正确的?我最初希望声明一个别名,同时进行替换检查,因为在
requires
子句中不可能声明类型别名。我希望无论编译器如何,
概念
的模板参数都能保持一致。也许我可以期待这会作为CWG的一部分进行讨论。@PHD:修复编译器错误不是CWG的责任。即使CWG更改了标准,也很可能会以这种方式使用
check\u type
成为编译错误(就像您尝试执行
check\u type
一样),而不是使其成为
requires
子句的事实部分。如果您想要
requires
子句中的内容,请将其放在那里。
template <typename T>
concept check_type = std::default_initializable<T> && requires { typename T::value_type; };