【问题标题】:Can requires-expression in C++20 be of type implicitly convertible to bool?C++20 中的 requires-expression 可以是隐式转换为 bool 的类型吗?
【发布时间】:2021-10-02 08:45:09
【问题描述】:

在以下示例中,第二个 f 函数重载的 requires 表达式具有 std::integral_constant<bool,true> 类型,可隐式转换为 bool

#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() { return 1; }。演示:https://gcc.godbolt.org/z/nf65zrxoK

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

【问题讨论】:

  • 我没有找到任何可以将任何表达式隐式转换为布尔值的东西。因此,gcc 对我来说看起来不错。要获得到 bool 的显式转换,您必须编写:std::bool_constant&lt; T::valid &gt;::value 或执行像 (bool)std::bool_constant&lt; T::valid &gt; 这样的显式转换。如果你想调用执行操作符,你必须在之前创建一个对象:std::bool_constant&lt; T::valid &gt;{}()。您忘记创建对象只是代码中的一个错字吗?

标签: c++ language-lawyer c++20 c++-concepts


【解决方案1】:

我相信 GCC 是正确的 — 类型必须是 bool,完全符合 [temp.constr.atomic]/3(注意这里的 Estd::bool_constant&lt; T::valid &gt;()):

要确定是否满足原子约束,首先将参数映射和模板参数代入其表达式。如果替换导致无效的类型或表达式,则不满足约束。否则,如有必要,将执行左值到右值的转换,并且 E 应为 bool 类型的常量表达式。当且仅当对 E 的评估结果为真时,才满足约束。如果在程序的不同点,对于相同的原子约束和模板参数,满足结果不同,则程序是非良构的,不需要诊断。 [ 例子:

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

—结束示例]

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2017-06-01
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多