在以下示例中,secondf
-函数重载的requires表达式的类型为std::integral\u常量
#include <type_traits>
struct S {
static constexpr bool valid = true;
};
template<typename T>
int f() { return 1; }
template<typename T>
int f() requires( std::bool_constant< T::valid >() ) { return 2; }
int main() {
return f<S>();
}
人们可以观察到GCC拒绝程序,因为类型不是精确的bool
,而是Clang接受,但选择另一个重载int f(){返回1;}
。演示:https://gcc.godbolt.org/z/nf65zrxoK
这里哪个编译器是正确的?
我相信GCC是正确的类型必须是bool
完全符合[temp.contr.atomic]/3(注意E
这里是std::bool\u常量
为了确定是否满足原子约束,首先将参数映射和模板参数替换到其表达式中。如果替换导致无效类型或表达式,则不满足约束。否则,如有必要,将执行从左值到右值的转换,E应为bool类型的常量表达式。当且仅当E的计算结果为true时,约束才得到满足。如果在程序中的不同点上,对于相同的原子约束和模板参数,满足结果不同,则程序格式不正确,不需要诊断。[示例:
template<typename T> concept C =
sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !true
template<typename T> struct S {
constexpr operator bool() const { return true; }
};
template<typename T> requires (S<T>{})
void f(T); // #1
void f(int); // #2
void g() {
f(0); // error: expression S<int>{} does not have type bool
} // while checking satisfaction of deduced arguments of #1;
// call is ill-formed even though #2 is a better match
-结束示例]