静的メンバーの初期化には、ネストされたヘルパー構造体を使用します。これは、テンプレート化されていないクラスで正常に機能します。ただし、包含クラスがテンプレートによってパラメーター化されている場合、メインコードでヘルパーオブジェクトにアクセスしないと、ネストされた初期化クラスはインスタンス化されません。説明のために、簡単な例(私の場合、ベクトルを初期化する必要があります)。
#include <string>
#include <iostream>
struct A
{
struct InitHelper
{
InitHelper()
{
A::mA = "Hello, I'm A.";
}
};
static std::string mA;
static InitHelper mInit;
static const std::string& getA(){ return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;
template<class T>
struct B
{
struct InitHelper
{
InitHelper()
{
B<T>::mB = "Hello, I'm B."; // [3]
}
};
static std::string mB;
static InitHelper mInit;
static const std::string& getB() { return mB; }
static InitHelper& getHelper(){ return mInit; }
};
template<class T>
std::string B<T>::mB; //[4]
template<class T>
typename B<T>::InitHelper B<T>::mInit;
int main(int argc, char* argv[])
{
std::cout << "A = " << A::getA() << std::endl;
// std::cout << "B = " << B<int>::getB() << std::endl; // [1]
// B<int>::getHelper(); // [2]
}
g ++ 4.4.1の場合:
[1]と[2]のコメント:
A =こんにちは、私はAです。
意図したとおりに動作します
[1]コメントなし:
A =こんにちは、私はAです。 B =
InitHelperがmBを初期化することを期待します
- [1]および[2]コメントなし:
A =こんにちは、私はAです。 B =こんにちは、私はBです。
意図したとおりに動作します - [1]コメント、[2]コメントなし:
[3]の静的初期化段階でのセグメンテーション違反
したがって、私の質問:これはコンパイラのバグですか、それともモニターと椅子の間にあるバグですか?そして後者の場合:洗練された解決策はありますか(つまり、静的初期化メソッドを明示的に呼び出さないでください)?
アップデートI:
これは望ましい動作のようです(ISO / IEC C ++ 2003標準、14.7.1で定義されています):
クラステンプレートのメンバーまたはメンバーテンプレートが明示的にインスタンス化されているか、明示的に特殊化されていない限り、メンバー定義が存在する必要があるコンテキストで特殊化が参照される場合、メンバーの特殊化は暗黙的にインスタンス化されます。特に、静的データメンバーの定義が存在する必要がある方法で静的データメンバー自体が使用されない限り、静的データメンバーの初期化(および関連する副作用)は発生しません。