提问人:303 提问时间:11/7/2023 更新时间:11/7/2023 访问量:152
格式错误的约束表达式
Ill-formed constraint expression
问:
关于函数,是非类型模板参数的替换约束表达式
模板化变量的有效常量表达式?C++20标准的具体措辞
允许还是禁止?f
b
struct s { static constexpr bool v = true; };
template<auto> inline constexpr bool b = true;
constexpr bool f(auto x) requires b<x.v> { return true; }
static_assert(f(s{})); // clang ok, gcc nope, msvc ok
来自 GCC 的错误消息:
<source>:3:36: error: missing template arguments before '<' token
3 | constexpr bool f(auto x) requires b<x.v> { return true; }
| ^
<source>:3:36: error: expected initializer before '<' token
<source>:4:15: error: 'f' was not declared in this scope
4 | static_assert(f(s{}));
| ^
答:
3赞
Artyer
11/7/2023
#1
此代码正确的原因是 [expr.const]p5 中的措辞不适用:
表达式 E 是一个核心常量表达式,除非按照抽象机器的规则 ([intro.execution]) 对 E 的计算将计算以下值之一:
- [...]
而且这些程序点都不适用。由于不对 应用左值到右值的转换,并且是一个常量表达式,您可以对其应用左值到右值的转换,因此(当类型为且不是引用时)是一个常量表达式。x.v
x
S::v
x.v
x
S
看起来 gcc 正在尝试解析为(作为两个关系运算符),因此会给你一个错误。这显然是一个错误,因为无论如何都应该是一个模板,因为这是一个模板化的实体。b<x.v>
(b < x.v) >
b<
b
此 gcc 错误的更多示例: https://godbolt.org/z/fP74hW1qs https://godbolt.org/z/19K4nYTjT
如果您使用说明符而不是说明符,则会收到一个有趣的附加错误消息:noexcept
requires
https://godbolt.org/z/8xqre5bbT(https://godbolt.org/z/cPYbb6vsq 用于尾随返回类型)
<source>:3:38: error: use of parameter outside function body before '.' token
3 | constexpr bool f(auto x) noexcept(b<x.v>) { return true; }
| ^
这让我认为在某些时候,在函数体之外命名函数参数会导致 GCC 出错,但是当它位于 .requires
评论
0赞
Fedor
11/9/2023
报告的 GCC 问题:gcc.gnu.org/bugzilla/show_bug.cgi?id=112448
评论
constexpr bool f(auto x) requires b<decltype(x)::v> { return true; }