格式错误的约束表达式

Ill-formed constraint expression

提问人:303 提问时间:11/7/2023 更新时间:11/7/2023 访问量:152

问:

关于函数,是非类型模板参数的替换约束表达式 模板化变量的有效常量表达式?C++20标准的具体措辞 允许还是禁止?fb

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{}));
      |               ^
C++ 语言-律师 C++20

评论

1赞 463035818_is_not_an_ai 11/7/2023
请注意,所有这些都很好。我不明白为什么你的 clang / msvc 没问题,但这可能只是我对 c++20 的无知constexpr bool f(auto x) requires b<decltype(x)::v> { return true; }
0赞 ecatmur 11/9/2023
相关新闻: stackoverflow.com/q/77440394/567292

答:

3赞 Artyer 11/7/2023 #1

此代码正确的原因是 [expr.const]p5 中的措辞不适用:

表达式 E 是一个核心常量表达式,除非按照抽象机器的规则 ([intro.execution]) 对 E 的计算将计算以下值之一:

  • [...]

而且这些程序点都不适用。由于不对 应用左值到右值的转换,并且是一个常量表达式,您可以对其应用左值到右值的转换,因此(当类型为且不是引用时)是一个常量表达式。x.vxS::vx.vxS


看起来 gcc 正在尝试解析为(作为两个关系运算符),因此会给你一个错误。这显然是一个错误,因为无论如何都应该是一个模板,因为这是一个模板化的实体。b<x.v>(b < x.v) >b<b

此 gcc 错误的更多示例: https://godbolt.org/z/fP74hW1qs https://godbolt.org/z/19K4nYTjT

如果您使用说明符而不是说明符,则会收到一个有趣的附加错误消息:noexceptrequires

https://godbolt.org/z/8xqre5bbThttps://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