2011-09-17 11 views
2

Iは、非テンプレートベースから検索派生テンプレートの種類

struct CBaseList { 
    virtual size_t Size() = 0; 
}; 

template <class T> 
struct CPointList : public BaseList { 
    virtual size_t Size() { return mData.size(); } 
    std::vector <T> mData; 
}; 

// Ok, now I can create various instances 
CBaseList * lst1 = new CPointList<float>(); 
CBaseList * lst2 = new CPointList<double>(); 

をテンプレートクラスを派生してきた。しかし、どのように私は/異なるインスタンス間で値を割り当てるコピーすることができますか?例えば、

template <class T1, class T2> 
void CopyVec(const T1 & src, T2 & dst) 
{ 
    dst.resize(src.size()); 
    for (size_t i = 0; i < src.size(); ++i) 
    dst[i] = src[i];  
} 

void CopyList(const CBaseList * src, CBaseList * dst) 
{ 
// How to call CopyVec ? 
} 

CBaseListを任意の派生クラスにキャストした場合、私は大きな「醜い」スイッチを持っています。より良い解決策はありますか?

おかげ イゴールご回答のため


thiton

感謝。どのコンパイラでもテンプレートからコードを生成するための型があることがわかっています。しかし、必要なテンプレート関数を複製することなく、コンパクトかつ一度実装する方法はありますか?

// caller 
theWrapper(lst1, lst2)->mInstance().DoCopy(lst1, lst2, num); 

// mInstance type 
template <class T1, class T2> 
struct CWrapInstance { 
void DoCopy(CBaseList * lst1, CBaseList * lst2, size_t num) 
{ 
    // cast types and call original template 
    Copy(((T1 *) lst1)->mData, ((T2 *) lst2)->mData, num); 
} 
}; 

したがって、新しいテンプレートごとにCWrapInstanceに小さなメソッドしか追加する必要はありません。しかし、どのように "theWrapper"を設計するのですか?

Thxご理解ください。 Igor

答えて

2

実行時にタイプを渡す方法はありません。型はファーストクラスのオブジェクトではなく、型はコンパイル時にのみ存在します。あなたは何ができるか

(例えばtypeid、またはあなた自身の列挙を作成することができますし、この列挙値を返すあなたのコンテナに仮想メソッドを追加することができます)タイプを中心にを渡しています。たとえばん

マシンコードはfloatdoubleからの変換はunsigned long longintからの変換を行い、C++プログラムは、実行時に使用すると、可能性のあるすべてのマシンコードを新しいコードを作成することができないということを忘れないでください、マシンコードとは明らかに異なっていますコンパイル時に実行時のニーズが作成されている必要があります。

多相データコンテナ(ランタイムポリモーフィズムを意味する)を作成し、インスタンス間で変換/割り当てを行う必要がある場合は、すべての変換コンビネーションのコードをコンパイル時に事前に作成する必要があります。タイプ名を使用して実行するコードも選択する必要があります。

だからはい。残念ながら、スイッチなどが必要です。

スイッチに代わる方法として、変換関数のマップを作成する方法があります。

template<typename U, typename V> 
void assign(CBaseList *u, CBaseList *v) 
{ 
    CPointList<U>* pu = dynamic_cast< CPointList<U> >(u); 
    CPointList<V>* pv = dynamic_cast< CPointList<V> >(v); 
    ... 
} 

void init_converters() 
{ 
    converters[std::make_pair(FLOAT_ID, DOUBLE_ID)] = &assign<float, double>; 
    converters[std::make_pair(INT_ID, DOUBLE_ID)] = &assign<int, double>; 
    ... 
} 

は、あなたが動的に割り当てることができます。あなたがマップであなたが必要としているすべての変換を格納できるように、2つのタイプの名前を与えられた

std::map< std::pair<int, int>, void (*)(CBaseList *, CBaseList *) > converters; 

は、変換関数のアドレスを返します。実行時に

converters[std::make_pair(a->id(), b->id())](a, b); 
1

私はあなたが栄光のスイッチを避けることができるとは思わないし、6502はそれを実行するための良い選択肢を投稿しました。問題は、あなたの型が形式的には何らかの形で関連していないということです。実際には、実行時には実行できないテンプレートからインスタンス化する必要があるn^2変換関数が必要です。私は別のデザインをお勧めしたいと思いますか?

関連する問題