在概念定义中,是否允许在 requires 表达式之外出现替换失败?

In concept definitions, are substitution failures allowed outside of a requires expression?

考虑这段代码:

#include <type_traits>                                           
#include <iostream>

template <class T> concept bool C1 = std::is_same<T, int>::value; 

template <class T> concept bool C2 =  
    C1<decltype(std::declval<T>() + std::declval<T>())>; 

struct A {};                   

int main() { 
  std::cout << C2<int>; 
  std::cout << C2<A>;                                                 
  return 0;                                                           
}

GCC 编译它 fine 并打印 10。

但是 §14.10.1.2 N4553 的谓词约束 [temp.constr.pred]

A predicate constraint is a constraint that evaluates a constant expression E (5.19).

然后

After substitution, E shall have type bool.

因为 C1<decltype(std::declval<A>() + std::declval<A>())> 是替换失败,而不是 bool 类型,这是否意味着程序应该是病式的?

Concepts TS 仅定义了用于确定声明的相关约束是否满足的行为;没有规定在关联约束之外引用概念名称。所以严格来说,std::cout << C<int>std::cout << C<A> 都是病式的。

EWG 决定在科纳将此作为一项新功能:

Straw poll: SF | F | N | A | SA

  • Should we allow evaluation of concepts anywhere? 8 | 6 | 2 | 0 | 0
  • Should we allow the presence and evaluation of a requires-expression in any expression? 1 | 2 | 10 | 3 | 1
    • Note that without the first poll, the second poll would change.

但是还没有具体说明其行为的措辞。

GCC 目前允许将概念作为表达式作为(我相信未记录的)扩展。我发现很可能会指定此功能,以便在将 X... 替换为 C 的初始值设定项无法生成有效表达式时,C<X...> 的计算结果为 false,并且otherwise 具有如此获得的表达式的值。这似乎是执行此操作的明智方法,并且与 GCC 中的实现一致。