繁体   English   中英

模板函数要求子句的原子约束中的替换失败

[英]Substitution failure in an atomic constraint of template function requires-clause

C++20 中的约束在通过将它们划分为原子约束来检查是否满足之前进行了规范化。 例如,约束E = E1 || E2 E = E1 || E2有两个原子约束E1E2

原子约束中的替换失败应视为原子约束的错误值。

如果我们考虑一个示例程序,则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
}

那么函数f<void,int>()满足要求,因为Complete<void>由于替换失败而仅评估为falseComplete<int>评估为true

但是类似的函数g<void,int>()使编译器产生分歧。 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) {}

演示: https : //gcc.godbolt.org/z/zedz7dMGx

函数fg不是真的相同,还是 Clang 在这里错了?

这是Clang 错误 #49513 情况和分析与这个答案类似。

sizeof(T)>0原子约束,因此[temp.constr.atomic]/3适用:

为了确定是否满足原子约束,首先将参数映射和模板参数代入其表达式。 如果替换导致无效的类型或表达式,则不满足约束。 [...]

sizeof(void)>0是无效表达式,因此不满足约束,并且约束评估继续进行sizeof(U)>0

与链接的问题一样,另一种解决方法是使用“ requires requires requires ”; 演示

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM