クラス内にstatic constexpr T
で宣言した定数を、std::vector::emplace_back()
関数とかに渡すと、リンクエラーになる場合があります。
ミニマムなコードとしては、以下のようになります:
struct X { static constexpr int x = 3; }; template <class T> void f(T&&) {} int main() { f(X::x); // リンクエラー : X::xの実体が見つからない }
クラスの静的定数は、宣言だけした場合にコピーはできますが、その変数のポインタや参照をとったりはできません。そのようなことをしたい場合は、どこかの.cpp/.ccといった拡張子のソースファイルで、変数を定義する必要があります。
struct X { static constexpr int x = 3; }; template <class T> void f(T&&) {} constexpr int X::x; // この翻訳単位にX::xの実体を置く int main() { f(X::x); // OK }
回避策として考えられるのは、以下のようなものです:
- C++17のインライン変数で定数を定義する (staticメンバ変数は自動的にインラインになる)
- constexpr変数ではなく、constexpr関数で定数を定義する