I would like a class C to have a static constexpr member of type C. Is this possible in C++11?
Attempt 1:
struct Foo {
constexpr Foo() {}
static constexpr Foo f = Foo();
};
constexpr Foo Foo::f;
g++ 4.7.0 says: ‘invalid use of incomplete type’ referring to the Foo() call.
Attempt 2:
struct Foo {
constexpr Foo() {}
static constexpr Foo f;
};
constexpr Foo Foo::f = Foo();
Now the problem is the lack of an initializer for the constexpr member f inside the class definition.
Attempt 3:
struct Foo {
constexpr Foo() {}
static const Foo f;
};
constexpr Foo Foo::f = Foo();
Now g++ complains about a redeclaration of Foo::f differing in constexpr.
If I interpret the Standard correctly, it isn’t possible.
From the above (along with the fact that there is no separate statement about non-literal types in static data member declarations), I believe it follows that a static data member that is
constexprmust be a literal type (as defined in §3.9/10), and it must have its definition included in the declaration. The latter condition could be satisfied by using the following code:which is similar to your Attempt 1, but without the class-external definition.
However, since
Foois incomplete at the time of declaration/definition of the static member, the compiler can’t check whether it is a literal type (as defined in §3.9/10), so it rejects the code.Note that there is this post-C++-11 document (N3308) which discusses various problems of the current definition of
constexprin the Standard, and makes suggestions for amendments. Specifically, the “Proposed Wording” section suggests an amendment of §3.9/10 that implies the inclusion of incomplete types as one kind of literal type. If that amendment was to be accepted into a future version of the Standard, your problem would be solved.