茂加部珈琲店

主にtech関連のメモ置き場です

static constで宣言してconstexprで初期化する

以下のコードはコンパイルに失敗します

struct Foo {
  // error: 'constexpr const Foo Foo::s' has incomplete type
  static constexpr Foo s = {}; 
};
constexpr Foo Foo::s;

constexprは宣言と初期化を一緒にしないといけないので、以下のようにしてもコンパイルできません。

struct Foo {
  // error: 'constexpr' static data member 's' must have an initializer
  static constexpr Foo s;
};
constexpr Foo Foo::s = {};

そういう時は、宣言をstatic constに変えるとコンパイルできます。

struct Foo {
  static const Foo s;
};
constexpr Foo Foo::s = {};

規格的にはおそらくこれは違法では無いと思いますが、私もいまいちよくわかってません。
static constで宣言された場合は、constexprで初期化されるまではconstexprで使用することはできません。
以下のコードはコンパイルできません

struct Foo {
  static const Foo s;
};
constexpr Foo g = Foo::s;
constexpr Foo Foo::s = {};

しかし、次のコードはコンパイルできます

struct Foo {
  static const Foo s;
};
constexpr Foo Foo::s = {};
constexpr Foo f = Foo::s;

これをヘッダと実装で分けたりするのはあまりおすすめできません