303*_*303 6 c++ language-lawyer c++20
require 子句中的表达式是否b<[]{ return true; }()>符合 C++20 标准?由于某种原因,GCC 拒绝它并认为它是表达式错误,而 MSVC 和 Clang 接受它。
template<bool B>
inline constexpr bool b = B;
static_assert(requires { b<[]{ return true; }()>; });
Run Code Online (Sandbox Code Playgroud)
GCC的错误信息:
<source>:3:15: error: static assertion failed
3 | static_assert(requires { b<[]{ return true; }()>; });
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:3:15: note: constraints not satisfied
<source>:3:26: note: the required expression 'b<<expression error> >' is invalid,
because
3 | static_assert(requires { b<[]{ return true; }()>; });
| ^~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
这是一个已确认的 GCC错误。需要表达式是静态断言的有效表达式。语法的深度标准很疯狂,但我们开始了。
根据语法:
之后唯一的问题是(根据[decl.pre])您提供的 require 子句是否满足以下条件:
[表达式] E 根据上下文转换为 bool,转换后的表达式应为常量表达式
嗯,根据[exp.prim.req.general] , requires 表达式肯定可以转换为布尔值
要求表达式是 bool 类型的纯右值 [...]
您的需求表达式是一个简单的需求,只需要一个可能依赖或不依赖模板替换的表达式。在您的情况下,没有模板替换,因此传递所需的只是requires一个有效的表达式,任何有效的表达式。您的 lambda 非常有效(并且constexpr)。但请注意,返回的 lambdafalse应该同样有效并导致静态断言也通过:
static_assert(requires { b<([](){ return false; }())>; }); // pass
Run Code Online (Sandbox Code Playgroud)
因此,使用 require 表达式而不进行模板替换可能不是一个好主意。
有趣的是, astatic_assert也可能有一个noexcept表达式,并且将 require 子句包装在一个表达式中会使GCC 13.2 通过:
static_assert(noexcept(requires { b<([]{ return true; }())>; }));
Run Code Online (Sandbox Code Playgroud)