提问者:小点点

C 20中的requires表达式是否可以隐式转换为bool类型?


在以下示例中,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

这里哪个编译器是正确的?


共1个答案

匿名用户

我相信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

-结束示例]

相关问题