Anyone know if there is something wrong with the following or if it is a bug?
#include <utility>
struct X {
template <typename...Ts>
static constexpr std::size_t fn() {
return 1;
}
static constexpr std::size_t value = fn();
};
Looks like msvc 19.22 seems to be ok with it, but clang and gcc don't like it.
If I move the fn() template external to the struct, it works fine. clang says:
error: constexpr variable 'value' must be initialized by a constant expression
and gcc says:
static constexpr std::size_t X::fn() [with Ts = {}; std::size_t = long unsigned int]' used before its definition
Also, can't define later:
struct X {
template <typename...Ts>
static constexpr std::size_t fn() {
return 1;
}
static constexpr std::size_t value;
};
constexpr std::size_t X::value = X::fn();
However, it can be specified as a constexpr function:
struct X {
template <typename...Ts>
static constexpr std::size_t fn() {
return 1;
}
static constexpr std::size_t value() {
return fn();
}
};
This appears to be caused by the class not being complete at use. If so, it would seem to be a deficiency since static member vars/fns don't depend on the class.
EDIT
Thanks @Rakete1111. Looking at the duplicate you provided, I got this quote from the standard (emphasis mine):
9.4.2 [class.static.data] p3: ... A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression.
As can is not the same as must, this further indicates a deficiency as my second example should have then worked.