简体   繁体   English

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

[英]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有两个原子约束E1E2

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>由于替换失败而仅评估为falseComplete<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?函数fg不是真的相同,还是 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.

相关问题 Requires-clause 出现在模板模板参数之后:这是合法的语法吗? - Requires-clause appears after template template parameter: is this legal grammar? 为什么类外成员模板定义需要重复其声明“requires-clause” - Why does an out-of-class member template definition need a repetition of its declaration 'requires-clause' 为什么可变参数模板在模板引入中不起作用,而在需求子句中起作用? ConceptName {T,U,V,W} &lt;—模板 <typename …T> - Why does variadic template not work in template introduction but work in requires-clause? ConceptName{T,U,V,W} <— template<typename …T> 使用std :: function的模板替换失败 - Template substitution failure with std::function 为什么需要在 requires 子句中的否定表达式周围使用括号? - Why are parentheses needed around negated expressions in a requires-clause? || 的无关可见过载防止|| 从要求子句中的短路 - Unrelated visible overload of || prevents || from short-circuiting in a requires-clause 替换失败的模板特化 - Template specialisation on substitution failure C ++模板函数,替换失败跳过实现 - C++ template function, substitution failure skip the implementation `std::function` 和之前推导出的模板参数替换失败 - 为什么? - Substitution failure with `std::function` and previously deduced template parameter - why? 模板模板参数的替换失败 - Substitution failure for template template argument
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM