2017-03-28 19 views
0

私が見つけた限りでは、クラステンプレート内の静的変数を初期化するための記事がありました。しかし、私はメンバ関数テンプレートで通常のクラスを使用しているので、私は尋ねなければなりません。ショートバージョンでテンプレート関数でクラス内の静的メンバ変数を初期化する方法

(全体ではないクラス定義)私はこのようになりクラスがあります。

class BatchManager 
{ 
    private: 

     static std::vector<BaseBatch_P> _BATCHES; 

    public: 

     template <class T> 
     static void placeData(T* data){ 

      //Loop through the entire container 
      for (auto&& b: _BATCHES) 
       if (b==data){ 
        dynamic_cast<Batch<T>>(b)->draw(data); 
       } 

      //If no bach found, create a new One 
      createNewBatch(data); 
     } 
}; 

を私は関数内のメンバ変数にアクセスしたい場合しかし、それは示しています 未定義クラスヘッダーに定義を保持:

BatchManagerを参照:: _ BATCHES

次にI'veは、以下を試し

そしてCPPファイル:

std::map<GLuint,BaseBatch_P> BatchManager::_TEXTURE_MAP; 

template <typename T> 
void BatchManager::placeData(T* data){ 

    //Loop through the entire container 
    for (auto&& b: _BATCHES) 
     if (b==data){ 
      dynamic_cast<Batch<T>>(b)->draw(data); 
     } 

    //If no bach found, create a new One 
    createNewBatch(data); 
} 

これは、最初の問題を修正したが、その後、別の現れ、と私はプログラムからの私の静的関数を呼び出したいときには起こる:

BatchManager::render(_data); 

エラーメッセージは次のようになります。

undefined reference to BatchManager::placeData<DataType>(DataType*) 

問題?または私は何か間違っているのですか?

+2

別に何か他のものから、アンダースコアと大文字で始まり\ _BATCHESのような名前は、C++の実装のために予約されている - あなたはあなた自身にそのような名前を作成するべきではありませんコード。 –

+0

なぜ私は私の個人的な容器にアンダースコアと大文字の名前を付けるような悪い習慣があるのか​​分かりません。それはいくつかの問題を引き起こす可能性があることを意味しますか?(この問題に関係しません) – Pins

+1

[クラステンプレートの静的メンバーの初期化]の可能な複製(http://stackoverflow.com/questions/3229883/static-member-initialization-in- –

答えて

1

このような何か:

#include <vector> 
#include <typeinfo> 

struct BaseBatch { 

    virtual const std::type_info& get_type() const = 0; 
    virtual ~BaseBatch() = default; 
}; 

template<class T> 
struct Batch : BaseBatch 
{ 

    const std::type_info& get_type() const override 
    { 
     return typeid(T); 
    } 

    void draw(T* data) {} 
}; 

using BaseBatch_P = BaseBatch*; 

class BatchManager 
{ 
private: 

    static std::vector<BaseBatch_P>& get_batches() { 
     static std::vector<BaseBatch_P> _; 
     return _; 
    } 

public: 

    template <class T> 
    static void placeData(T* data){ 

     //Loop through the entire container 
     bool found = false; 
     for (auto&& b: get_batches()) 
      if (b->get_type() == typeid(T)) { 
       dynamic_cast<Batch<T>*>(b)->draw(data); 
       found = true; 
      } 

     //If no bach found, create a new One 
     if (not found) { 
      get_batches().push_back(new Batch<T>); 
     } 
    } 
}; 
+0

うわー、それはうまく動作します!このアプローチに関するいくつかの追加情報を教えてください。私はこのようなものが初めて見えることを認めなければならない。 – Pins

+0

クラス宣言で静的メンバー変数を定義することはできませんが、静的関数を定義することはできます。私は理由は分かりません。なぜなら、30年前にできなかった歴史的な理由から、まだ誰も解決していないということでしょう。 あなたがやっていることは、「アヒルのように見え、アヒルのようなものであれば、アヒルです。それは「コードを使用してコードを検索する」というものです。これは「悪」です。 このアプローチは完全ではありません。 'int'へのポインタを渡すと、' const int'のためにタイプされたバッチと一致しません。私がさらにコメントする前に、あなたが達成しようとしていることを理解する必要があります。 –

+0

主な考え方は、一般的なバッチのコンテナを保持するシングルトン(BatchManager)を持つことです(このコードはOpenGLバッチ処理の一部で、GPUに送る前に頂点を格納するためのものです)。私は時々私は6つの頂点(通常は構造体の配列を渡す)、時には2(線を描画するため)などを渡したいので、私はそれは一般的な持っているので、私は何かを描画する必要があるとき、既に作成されたバッチのプールを介して、同じタイプがすでに存在するかどうかを判断します(新しいものを作成しない場合)。 BaseBatchは多型性の可能性のためだけに使用されます。 – Pins

関連する問題