[英]Substitution failure in an atomic constraint of template function requires-clause
Constraints in C++20 are normalized before checked for satisfaction by dividing them on atomic constraints. C++20 中的约束在通过将它们划分为原子约束来检查是否满足之前进行了规范化。 For example, the constraint
E = E1 || E2
例如,约束
E = E1 || E2
E = E1 || E2
has two atomic constrains E1
and E2
E = E1 || E2
有两个原子约束E1
和E2
And substitution failure in an atomic constraint shall be considered as false value of the atomic constraint.原子约束中的替换失败应视为原子约束的错误值。
If we consider a sample program, there concept Complete = sizeof(T)>0
checks for the class T
being defined:如果我们考虑一个示例程序,则
concept Complete = sizeof(T)>0
检查定义的类T
:
template<class T>
concept Complete = sizeof(T)>0;
template<class T, class U>
void f() requires(Complete<T> || Complete<U>) {}
template<class T, class U>
void g() requires(sizeof(T)>0 || sizeof(U)>0) {}
int main() {
f<void,int>(); //ok everywhere
g<void,int>(); //error in Clang
}
then the function f<void,int>()
satisfies the requirements, because Complete<void>
just evaluates to false
due to substitution failure and Complete<int>
evaluates to true
.那么函数
f<void,int>()
满足要求,因为Complete<void>
由于替换失败而仅评估为false
而Complete<int>
评估为true
。
But a similar function g<void,int>()
makes the compilers diverge.但是类似的函数
g<void,int>()
使编译器产生分歧。 GCC accepts it, but Clang does not: GCC 接受它,但 Clang 不接受:
error: no matching function for call to 'g'
note: candidate template ignored: substitution failure [with T = void, U = int]: invalid application of 'sizeof' to an incomplete type 'void'
void g() requires(sizeof(T)>0 || sizeof(U)>0) {}
Demo: https://gcc.godbolt.org/z/zedz7dMGx演示: https : //gcc.godbolt.org/z/zedz7dMGx
Are the functions f
and g
not really identical, or Clang is wrong here?函数
f
和g
不是真的相同,还是 Clang 在这里错了?
This is Clang bug #49513 ;这是Clang 错误 #49513 ; the situation and analysis is similar to this answer .
情况和分析与这个答案类似。
sizeof(T)>0
is an atomic constraint , so [temp.constr.atomic]/3 applies: sizeof(T)>0
是原子约束,因此[temp.constr.atomic]/3适用:
To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression.
为了确定是否满足原子约束,首先将参数映射和模板参数代入其表达式。 If substitution results in an invalid type or expression, the constraint is not satisfied.
如果替换导致无效的类型或表达式,则不满足约束。 [...]
[...]
sizeof(void)>0
is an invalid expression, so that constraint is not satisfied, and constraint evaluation proceeds to sizeof(U)>0
. sizeof(void)>0
是无效表达式,因此不满足约束,并且约束评估继续进行sizeof(U)>0
。
As in the linked question, an alternative workaround is to use " requires requires requires ";与链接的问题一样,另一种解决方法是使用“ requires requires requires ”; demo :
演示:
template<class T, class U>
void g() requires(requires { requires sizeof(T)>0; } || requires { requires sizeof(U)>0; }) {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.