2017-05-05 3 views
4

テンプレートがインスタンス化されている(低レベルのドライバの初期化に使用される)場合にのみ、いくつかのコードを実行するプログラムを作成しようとしています。 私は以下の解決策を持っています。テンプレートの静的メンバーのインスタンス化を強制する

class Initializer 
{ 
public: 
    Initializer(){ 
     // This code is executed once 
    } 

    void silly() const{ 

    } 
}; 

template <class T> 
class Proxy{ 
protected: 
    static const Initializer init; 
}; 

template<class T> 
const Initializer Proxy<T>::init; 

template<class T> 
class MyTemplate : public Proxy<void>{ 
public: 
    static void myMethod1(){ 
     init.silly(); 

     // ... Something useful 
    } 

    static void myMethod2(){ 
     init.silly(); 

     // ... Something useful 
    } 
}; 

Initializerデフォルトコンストラクタは、私がどこかにmyMethod1()myMethod2()を呼び出す場合にのみ実行されます。

しかし、これらの行を取り除く方法はありますか。init.silly();

+0

「インスタンス化の強制:」と「インスタンス化の確認」は、2つの方法が異なります。 –

+0

'Proxy'のインスタンスごとに' Initializer'を作成しますか?例えば。 'Proxy 'と 'Proxy 'を作成すると、 'Initializer'が2回構築されますか? – Pavel

+0

いいえ、「Initializer」のインスタンスを1つだけ作成します。私はいつも 'Proxy 'から継承します。 – valentin

答えて

2

テンプレートのメンバーは、参照されていない限りインスタンス化されません。

よりもむしろinit.silly()を呼び出して、あなただけのメンバーを参照することができます。

static void myMethod1(){ 
     (void)init; 

     // ... Something useful 
    } 

それとも、あなたはinitは絶対に常に定義されるようにしたい場合は、明示的にインスタンス化することができます

template<> 
const Initializer Proxy<void>::init{}; 
+0

良いですが、さらに1行のコードが必要です。 'init'の明示的なインスタンス化を使用すると、' MyTemplate'がインスタンス化されていなくてもコンストラクタが実行されます。そうではありません。 – valentin

1

テンプレートと低レベルのドライバーの初期化?..私は可能な限りCにしようとしています:)正確な動作を確保する。

あなたはこのおそらくのような何かを行うことができます:

class Initializer 
{ 
public: 
    Initializer() { 
     // This code is executed once 
    } 
}; 

template <class T> 
class Proxy { 
protected: 
    Proxy() 
    { 
     static Initializer init; 
    } 
}; 

template<class T> 
class MyTemplate : public Proxy<void> { 
public: 
    void myMethod1() { 
     // ... Something useful 
    } 

    void myMethod2() { 
     // ... Something useful 
    } 
}; 

あなたのすべてのコードは、静的な関数を使用して、クラスやテンプレートを使用する理由は本当に表示されません。私の変更で、myMethod1myMethod2を非staticにし、Proxy()コンストラクタでInitializerを1回作成しました。

テンプレートの混乱のため、Initializerは、Proxyテンプレートをインスタンス化する回数だけ実行されることがあります。本当にそれを意味しましたか?そうでない場合は、この予期しない結果を持たない明確な可読コードに変換してください。また、これは他の人のための優れた保守性と読めるようになります。

class Initializer 
{ 
    Initializer() { 
     // This code is executed once 
    } 
public: 
    void init() 
    { 
     static Initializer init; 
    } 
}; 


template<class T> 
class MyTemplate { 
public: 
    static void myMethod1() { 
     Initializer::init(); 
     // ... Something useful 
    } 

    static void myMethod2() { 
     Initializer::init(); 
     // ... Something useful 
    } 
}; 

これは、それが絶対的に明確InitializermyMethod1またはmyMethod2が呼び出される直前に一度だけ作成されることになります。何もあなたのInitializer::initを呼び出す場合、そのコードはInitializerからリンク時に削除する必要があります。

+0

あああ!それははるかにクリーンです。また、テンプレートメンバーがインスタンス化される時期についての詳細な質問を心配する必要もなくなります。これは、a)開発者が混乱する標準の暗いコーナーの一種です。 b)*コンパイラ*開発者はときどき混乱します。 –

関連する問題