3

それぞれ const 静的メンバー変数を含む 2 つのテンプレート化された構造があります。これらのメンバー変数の 1 つの初期化は、2 番目のメンバー変数に依存します。したがって、2番目が最初の前に初期化されることを保証できるようにしたいと思います。簡単な例を次に示します。

依存関係.hpp:

template<typename T, T> struct value { };

template <typename T>
struct Dependency {
  Dependency() {}
  Dependency(T v) : var(v) {}
  const static Dependency staticVar;
  T var;
};

template <typename T>
const Dependency<T> Dependency<T>::staticVar = Dependency<T>(1.5);

testStruct.hpp:

#include "dependency.hpp"

//template class Dependency<double>; [1]
//template class Dependency<float>;  [2]

template <typename T>
struct TestStruct {
  TestStruct(Dependency<T> v) : var(v.var) {}

  const static TestStruct staticVar;
  T var;
};

template <typename T>
const TestStruct<T> TestStruct<T>::staticVar = TestStruct<T>(Dependency<T>(Dependency<T>::staticVar));

test.cpp:

#include <iostream>
#include "testStruct.hpp"

using namespace std;

int main(int argc, char *argv[])
{
  cout << "TestStruct<d> " << TestStruct<double>::staticVar.var << endl;
  cout << "Dependency<d> " << Dependency<double>::staticVar.var << endl;

  cout << endl;

  cout << "Dependency<f> " << Dependency<float>::staticVar.var << endl; // [3]
  cout << "TestStruct<f> " << TestStruct<float>::staticVar.var << endl;

  return 0;
};

メインの出力は

TestStruct<d> 0
Dependency<d> 1.5

Dependency<f> 1.5
TestStruct<f> 1.5

つまり、TestStruct<T>が既に type に対してインスタンス化されているstaticVar場合、 は正しく初期化されますが、それ以外の場合はまだ初期化されていないため、0 のままです。[1] と [2] のコメントを外すと、タイプとの問題が解決します(つまり、[3] がコメントされていても、すべてが 1.5 を出力します)。それらを使用しないコードの型。T の型を指定しなくても、 (または) に何かを入れて、その型に対してインスタンス化されていることを保証できるようにしたいと考えています。DependencyTDependency<T>::staticVarfloatdoubleTestStruct<T>testStruct.hppDependency

C++ の静的メンバーの初期化 (内部のテンプレートの楽しみ)静的メンバーを強制的に初期化する方法を見てきました。. 最初のものは状況をよく説明していますが、私のような問題の解決策を提案していません。2番目には2つの解決策がありますが、どちらもGCC 4.2.1では機能しないようです(または、間違って適用しました...)。

私が試すべき他のトリックや回避策はありますか、それとも明示的なインスタンス化にこだわっていますか?

4

1 に答える 1

1

cdhowie で提案されているように、静的メソッドを使用してTestStructとの間の初期化順序を確保できますDependency。静的メソッドではなく静的変数の外観を維持することに本当に関心がある場合は、静的メソッド呼び出しによって初期化される静的参照変数を使用できます。

グローバル初期化コンテキスト中に安全に呼び出すことができるように、静的メソッドの実装自体が静的参照変数を使用しないようにする必要があるだけです。

template <typename T>
struct Dependency {
  Dependency() {}
  Dependency(T v) : var(v) {}
  static const Dependency & staticMethod () {
      static const Dependency staticMethodVar(1.5);
      return staticMethodVar;
  }
  static const Dependency & staticVar;
  T var;
};

template <typename T>
const Dependency<T> & Dependency<T>::staticVar
        = Dependency<T>::staticMethod();

template <typename T>
struct TestStruct {
  TestStruct(Dependency<T> v) : var(v.var) {}
  static const TestStruct & staticMethod () {
      static const TestStruct staticMethodVar(Dependency<T>::staticMethod());
      return staticMethodVar;
  }
  static const TestStruct & staticVar;
  T var;
};

template <typename T>
const TestStruct<T> & TestStruct<T>::staticVar
        = TestStruct<T>::staticMethod();
于 2015-04-10T20:28:40.593 に答える