【问题标题】:Ad-hoc constraint requires requires requires requires?临时约束需要需要需要需要吗?
【发布时间】:2021-06-08 05:52:26
【问题描述】:

假设我正在编写一个类模板,其中一些成员受限于类型模板参数静态 constexpr 数据成员的存在 和值

template<class T>
struct A {
    constexpr bool operator()() requires T::value { return T::value; }
    constexpr bool operator()() { return false; }
};
#include <type_traits>
static_assert(A<std::true_type>()());
static_assert(!A<std::false_type>()());
static_assert(!A<void>()());

MSVC 和 gcc 接受这个,但 clang 拒绝,除非我 replace requires T::valuerequires requires { requires T::value; }。这是clang中的错误,还是其他编译器松懈?是C++需要需要需要需要的情况吗?标准是怎么说的?

相关(嗯,至少 ⅔):Why do we require requires requires?

【问题讨论】:

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


    【解决方案1】:

    这是一个clang错误(已提交#49513)。

    看起来clang 正在将void 替换为T::value 并决定因为这是一个无效的表达式,所以约束是无效。但是[temp.constr.atomic] 的规则是:

    要确定是否满足原子约束,首先将参数映射和模板参数代入其表达式。如果替换导致无效的类型或表达式,则不满足约束。

    在这种情况下,替换会导致无效的类型或表达式,因此其结果应该是不满足约束。


    注意这个重载:

    constexpr bool operator()() requires T::value { return T::value; }
    

    仅当T::value 是一个有效的表达式并且 计算结果为true 时才有效。这使得它等同于:

    constexpr bool operator()() requires T::value { return true; }
    

    在这种情况下这很好,因为在另一种情况下你会返回 false,所以没有理由区分 T::value 存在但 falseT::value 不存在。

    但认为无论如何都值得澄清。

    【讨论】:

    • 啊,是的,我可能把这个例子简单化了。使用(很多)上下文会更有意义。
    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 2017-10-14
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 2013-02-13
    相关资源
    最近更新 更多