https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127614
--- Comment #1 from ivan <irvsrc at gmail dot com> ---
I made some errors in that report, which I have now amended.
Please refer to this version instead:
As shown below, `b2` and `b3` (static constexpr members with placeholder type
and requires-expression initializer) defer instantiations of their definitions
despite those definitions being required to exist.
As a result, both evaluate to true, however should both evaluate to false.
```
template<typename t>
struct base {
bool constexpr static b1 = requires { t::d; }; // declaration instantiated,
definition not instantiated, ok
auto constexpr static b2 = requires { t::d; }; // declaration instantiated,
definition not instantiated, error, definition should be instantiated
decltype(auto) constexpr static b3 = requires { t::d; }; // error also
occurs with placeholder type decltype(auto), not just auto
// int constexpr static b4 = t::d; // well-formed, ok
// auto constexpr static b5 = t::d; // ill-formed, ok
// decltype(auto) constexpr static b6 = t::d; // ill-formed, ok
};
struct deri : base<deri> {
auto constexpr static d = 0;
};
auto main() -> int {
static_assert(deri::b1); // ok
static_assert(!deri::b2); // error
static_assert(!deri::b3); // error
}
```
- `bool constexpr static b1 = requires { t::d; };`
[temp.inst] (3) (3.1) (4) requires instantiation of the declaration, but not
its definition unless used in a way that requires it to exist (which here it is
not).
Since its type is already known, its definition should not be instantiated
until it is needed, by which point `deri` is complete, and the
requires-expression should evaluate to true.
This does happen, so this is correct.
- `auto constexpr static b2 = requires { t::d; };`
- `decltype(auto) constexpr static b3 = requires { t::d; };`
[dcl.spec.auto] (5) requires the declaration's type to be deduced from its
initializer, and is therefore used in a way that requires the definition to
exist.
This occurs during the instantiation of `base<deri>`, while `deri` is
incomplete, and therefore [expr.prim.req] (5) requires the requires-expression
to evaluate to false.
This does not happen, so this is incorrect.
Notes:
As shown in the example, this incorrect behavior:
- Occurs with both placeholder types `auto` and `decltype(auto)`
- Occurs only when the expression is a requires-expression (from my tests)
- Occurs across all GCC and C++ versions supporting requires-expression
Compile with at least C++20 or later.