静的(constexpr)メンバのリンケージについては、多くの回答があります。静的constexprメンバを持つテンプレートクラスのODR
しかし、テンプレートクラスのアウトオブライン定義をヘッダファイルで使用するのはなぜですか?特殊なクラスでは機能しません。
A)これはリンカエラーなしで動作します:
template<typename, typename>
struct Foobar;
template<typename T>
struct Foobar<int, T> {
static constexpr std::array<int, 1> a = {{1}};
};
template<typename T>
constexpr std::array<int, 1> Foobar<int, T>::a;
// foo.cpp
std::cout << Foobar<int, int>::a[0] << "\n";
// bar.cpp
std::cout << Foobar<int, int>::a[0] << "\n";
のobjdumpは:
のfoo.o:0000000000000000 w O .rodata._Z6FoobarIiiE1aE 0000000000000004 _Z6FoobarIiiE1aE
bar.o:0000000000000000 w O .rodata._Z6FoobarIiiE1aE 0000000000000004 _Z6FoobarIiiE1aE
リンクされたファイル:0000000000475a30 w O .rodata 0000000000000004 _Z6FoobarIiiE1aE
b)これ(複数定義)されていません。
template<typename>
struct Foobar;
template<>
struct Foobar<int> {
static constexpr std::array<int, 1> a = {{1}};
};
constexpr std::array<int, 1> Foobar<int>::a;
// foo.cpp
std::cout << Foobar<int>::a[0] << "\n";
// bar.cpp
std::cout << Foobar<int>::a[0] << "\n";
のobjdumpは:
foo.oの0000000000000100 g O .rodata 0000000000000004 _Z6FoobarIiE1aE
bar.o:0000000000000420 g O .rodata 0000000000000004 _Z6FoobarIiE1aE
我々が見る何を、アウトオブライン定義オブジェクトファイル内のアドレスが異なります(例b)。
あなたへの私の質問:
- が、それはテンプレートのトリックを使用することを保存しますか?欠点は何ですか?
- 将来的にbのようなケースでodrの定義を緩和すると便利でしょうか?
ありがとうございます!
「*将来的には、Bのようなそのような場合のためのODRの定義を緩和することは有用であろう*?」すでにC++ 17で:constexprの静的データメンバーは暗黙的に 'インライン'です。 – ildjarn
素敵!それを待つことはできません。 :) – Viatorus