Vai*_*Man 25 c++ language-design language-lawyer c++-concepts c++20
在此代码中,
template<class T, class U>
concept always_true = true;
template<class T>
concept always_true_if_tagged = always_true<T, typename T::tag>;
struct A {
using tag = int;
};
static_assert(always_true_if_tagged<A>);
static_assert(!always_true_if_tagged<int>); //GCC says this failed
Run Code Online (Sandbox Code Playgroud)
GCC 表示第二个断言失败。Clang 和 MSVC 都同意编译它。
我最初认为它是不正确的,不需要诊断,因为temp.constr.normal#1.4
概念 ID 的范式
C<A1, A2, ..., An>是 的约束表达式的范式C,在替换A1, A2, ..., An每个C原子约束中的参数映射中的各自模板参数后。如果任何此类替换导致无效类型或表达式,则该程序格式错误;无需诊断。
替换T::typename tag是 的参数映射always_true,因此格式错误;无需诊断。
所以我的前两个问题是
解决方案之一是检查之前的嵌套类型名。所以参数映射always_true不会发生。
template<class T>
concept always_true_if_tagged =
requires {typename T::tag;}
&& always_true<T, typename T::tag>;
Run Code Online (Sandbox Code Playgroud)
为了确定是否满足原子约束,首先将参数映射和模板实参替换到其表达式中。如果替换导致无效类型或表达式,则不满足约束。否则,如有必要,将执行左值到右值的转换,并且
E应为 类型的常量表达式bool。E当且仅当评估结果为 时,约束才被满足true。如果在程序的不同点,对于相同的原子约束和模板参数,满足结果不同,则该程序是格式错误的,不需要诊断。
如果我写
template<class T>
concept always_true_if_tagged = bool(always_true<T, typename T::tag>);
Run Code Online (Sandbox Code Playgroud)
bool(always_true<T, typename T::tag>)是原子约束 IIUC。T::typename tagwith的替换会T=int导致无效类型,因此它应该是格式良好的且不满足。
所以我的最后两个(或四个)问题是
3.1. 这个替换是concept-id的参数映射吗always_true?
3.2. always_true是在concept C = always_true<T, typename T::tag>原子约束中使用吗?temp.constr.constr#general-1表示存在三种不同类型的约束:合取、析取和原子约束。
concept C = always_true<T, typename T::tag>像T=int这样的形式良好呢?(不过可能与第二个问题相同)编辑:正如我在评论中所说,我注意到这个已回答的问题。但这是一个“WHY”的问题,不仅仅是问标准中定义了什么,更重要的是动机是什么。例如,标准不能考虑always_true_if_tagged<int>格式良好且不满足的原因是什么,正如我在该答案的评论中所问的那样(并且尚未回复),我们可以通过仅添加requires {typename T;}but typename Tis已经在参数列表中来解决这个问题,这使得解决方案似乎多余。
Vir*_*co_ -4
你猜对了吗?[\xe2\x80\xa6]
\ntypename T::tag是的\xe2\x80\x99t 不会使用[T = int].
为什么它应该是格式错误的?
\n你说的理由是对的。typename int::tag简直是无稽之谈。
\n根据记忆,您\xe2\x80\x99d 还需要将模板专业化移动到 下方以在模板中struct A使用。typename A::tag
为什么 [\xe2\x80\xa6]
\n我不\xe2\x80\x99t相信这是格式良好的,因为\xc2\xa77.3.2 [conv.lval]
\n我不\xe2\x80\x99t 有答案问题,只有更多问题。
在概念中,它\xe2\x80\x99s不是模板实例化(请参阅:[temp.concept]、[temp.spec]、[temp.dep]),所以我不\xe2\x80\x99不明白那是如何实现的是一个原子约束(它是一个常量表达式吗?它如何计算出任何值)。
\nclang 14.0.0 不会\xe2\x80\x99t 生成带有-fsanitize=undefinedon 的警告
另请参阅:
\n SFINAE