3

각각 const 정적 멤버 변수가 포함 된 두 개의 템플릿 구조가 있습니다. 이러한 멤버 변수 중 하나의 초기화는 두 번째 멤버에 따라 다릅니다. 따라서 두 번째가 첫 번째 전에 초기화된다는 것을 보장 할 수 있기를 원합니다.템플릿 구조에서 const 정적 멤버의 초기화 순서를 보장하는 방법

dependency.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>staticVarT 유형으로 이미 인스턴스화되었지만 Dependency<T>::staticVar이 아직 초기화되지 않았기 때문에 0으로 유지되면 올바르게 초기화됩니다. [1]과 [2]의 주석을 제거하면 타입이 floatdouble 인 문제가 해결됩니다. (즉, 주석은 [3]이더라도 모든것이 출력됩니다.) 가능한 모든 가능한 유형을 나열하거나 템플릿을 인스턴스화하지 않아도되는 것이 더 좋습니다 코드를 사용하지 않는 유형의 경우 어떤 유형이 T인지 지정할 필요없이 해당 유형에 대해 Dependency이 인스턴스화되었음을 보증하기 위해 TestStruct<T> (또는 testStruct.hpp)에 무엇인가 넣을 수 있습니다.

나는 C++ Static member initalization (template fun inside)How to force a static member to be initialized?을 보았다. 첫 번째 상황을 잘 설명하지만, 내 같은 문제에 대한 해결책을 제안하지 않습니다. 두 번째는 두 가지 해결책을 가지고 있지만 GCC 4.2.1에서 제대로 작동하지 않는 것으로 보입니다 (또는 잘못 적용 했음).

시도해 봐야 할 다른 트릭이나 해결 방법이 있습니까? 아니면 명시적인 인스턴스화가 필요합니까?

+0

죄송합니다. 속임수라고 생각합니다. –

+0

[This] (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15)는 좋은 읽을 거리이며 문제를 해결할 수 있습니다. – cdhowie

+0

@cdhowie 정적 변수를 정적 함수로 바꾸려면 인터페이스에 대한 (사소한) 변경이 필요합니다.이 구조를 사용하는 기존 코드가 있으므로 가능한 경우 만들지 않는 것이 좋습니다. 그것은 최선의 선택이 될 수 있습니다. – surtur

답변

0

cdhowie의 제안에 따라 TestStructDependency 사이의 초기화 순서를 보장하는 정적 방법을 사용할 수 있습니다. 정적 메서드가 아닌 정적 변수의 모양을 유지하는 것이 정말로 염려되는 경우 정적 메서드 호출로 초기화되는 정적 참조 변수를 사용할 수 있습니다.

전역 초기화 컨텍스트에서 안전하게 호출 할 수 있도록 정적 메서드 구현 자체에서 정적 참조 변수 만 사용하면됩니다.

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();