临时约束需要需要需要需要吗?

eca*_*mur 6 c++ compiler-errors language-lawyer c++-concepts c++20

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

\n
template<class T>\nstruct A {\n    constexpr bool operator()() requires T::value { return T::value; }\n    constexpr bool operator()() { return false; }\n};\n#include <type_traits>\nstatic_assert(A<std::true_type>()());\nstatic_assert(!A<std::false_type>()());\nstatic_assert(!A<void>()());\n
Run Code Online (Sandbox Code Playgroud)\n

MSVC 和 gcc 接受这一点,但 clang 拒绝,除非我替换 requires T::valuerequires requires { requires T::value; }. 这是 clang 中的错误,还是其他编译器松懈?C++ 是否需要需要需要需要?标准怎么说?

\n

相关(嗯,至少是\xe2\x85\x94):为什么我们需要需要需要?

\n

Bar*_*rry 4

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

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

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

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


请注意,此重载:

constexpr bool operator()() requires T::value { return T::value; }
Run Code Online (Sandbox Code Playgroud)

T::value仅当是有效表达式计算结果为 时才有效true。这使得它相当于:

constexpr bool operator()() requires T::value { return true; }
Run Code Online (Sandbox Code Playgroud)

在这种情况下这很好,因为false无论如何你都会在另一种情况下返回,所以没有理由区分T::value存在但false来自T::value存在。

但认为无论如何还是值得澄清的。