eca*_*mur 6 c++ compiler-errors language-lawyer c++-concepts c++20
假设我正在编写一个类模板,其中一些成员受到类型模板参数 static constexpr 数据成员的存在和值的限制:
\ntemplate<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)\nMSVC 和 gcc 接受这一点,但 clang 拒绝,除非我替换 requires T::value
为requires requires { requires T::value; }
. 这是 clang 中的错误,还是其他编译器松懈?C++ 是否需要需要需要需要?标准怎么说?
相关(嗯,至少是\xe2\x85\x94):为什么我们需要需要需要?
\n这是一个 clang bug(已提交#49513)。
看起来 clang 正在替换void
并T::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
存在。
但认为无论如何还是值得澄清的。