Regarding function f, is the substituted constraint expression of the non-type template argument
of templated variable b a valid constant expression? Which specific wording of the C++20 standard
either allows or forbids this?
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
Live example
The error message from 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{}));
| ^
The reason this code is correct is that non of the wording in [expr.const]p5 applies:
An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
- [...]
And none of the proceeding points apply. Since x.v does not apply an lvalue-to-rvalue conversion on x, and S::v is a constant expression which you can apply an lvalue-to-rvalue conversion on, x.v (when x is of type S and is not a reference) is a constant expression.
It looks like gcc is trying to parse b<x.v> as (b < x.v) > (as two relational operators), and so giving you an error. This is clearly a bug, as b< should be a template no matter what since b is a templated entity.
More examples of this gcc bug happening: https://godbolt.org/z/fP74hW1qs https://godbolt.org/z/19K4nYTjT
If you use the noexcept specifier instead of requires you get an interesting additional error message:
https://godbolt.org/z/8xqre5bbT (https://godbolt.org/z/cPYbb6vsq for trailing return type)
<source>:3:38: error: use of parameter outside function body before '.' token
3 | constexpr bool f(auto x) noexcept(b<x.v>) { return true; }
| ^
Which makes me think at some point naming function parameters outside of the function body makes GCC error out but the warnings aren't well written when it's inside a requires.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With