2011-12-23 5 views
2

をメンバ変数を置換、例えばC++ Iはnメンバ変数を持つクラスのTを有する他の種類の値で

class T{ 
    ushort name; 
ushort id; 
double value; 
.....etc... 
}; 

ために私はまた、それぞれの部材からなる、...、クラスT1のコレクションを有するT2変数 は、Tのメンバ変数のサブセットです(より良い単語がないため、 をTのサブセットタイプと呼びましょう)。例えば、T1はちょうど私が方法

template <typename X> 
T join(T t, X x) 
我々により、型Tのクラスを返す

を記述したいT.の2人のメンバー

をピックアップ

class T1 { 
ushort name; 
double value; 
}; 

であってもよいですtの各メンバー変数の値を x(XはTのサブタイプ)のものと置き換え、他のtの値は同じままです。

私は専門化によってこれを行うことができます。しかし、これを行うためのエレガントな方法が必要です(おそらく、タイプXがサブセットタイプのTであることを検出して正しいことを行う)。

答えて

0

私は専門化によってこれを行うことができます。しかし、これを行うためのエレガントな方法が必要です(おそらく、タイプXがサブセットタイプのTであることを検出して正しいことを行う)。

「検出」は、特殊化の一部です。 「サブセット」型の特殊化を提供し、汎用化のための実装を提供しないでください(そのメソッドで他の型を使用するとコンパイルエラーが発生します)。

0

すべてのサブセットタイプに特化を提供したくない場合。 MSVCを使用している場合は、メンバー検出器イディオム:Member Detectorまたは__if_existを使用してみてください。 だから、あなただけの代わりにT

CREATE_MEMBER_DETECTOR(name); 
CREATE_MEMBER_DETECTOR(id); 
CREATE_MEMBER_DETECTOR(value); 
...... 

template<int N, typename T, typename R> 
class SetName 
{ 
public: 
    void operator()(T& t, R& r) 
    { 
    } 
}; 

template<typename T, typename R> 
class SetName<1, T, R> 
{ 
public: 
    void operator()(T& t, R& r) 
    { 
     t.name = r.name; 
    } 
}; 
...... 
(can be macros too) 

とでメンバーのすべての可能な組み合わせを専門の[Tのメンバー数] * 2つのマクロ(および使用MSVCは、あなたがのsetXXXを必要としない場合)を記述する必要がありますでなければなりません)(参加:

template <typename SUBSET> 
T join(T t, SUBSET x) 
{ 
    SetName<Detect_name<SUBSET>::value, T, SUBSET>()(t, x); 
    SetValue<Detect_value<SUBSET>::value, T, SUBSET>()(t, x); 
    ...... 

    return t; 
} 
0

これを試してみてください:

#include <iostream> 
#include <typeifo> 

using namespace std; 

template<typename T> 
struct SetBase 
{ 
    T first; 
    T second; 
    SetBase(const T& first = T(), const T& second = T()) 
    : first(first), second(second) {} 
}; 

template<typename T> 
struct Set : public SetBase<T> 
{ 
    short name_id; 
    Set(const T& first = T(), const T& second = T(), const short& name) : 
    SetBase<T>(first, second), name_id(name){} 
}; 

template<typename Class, typename BaseClass> 
Class* join(Class **a, BaseClass *b) 
{ 
    if(typeid(Class) != typeid(BaseClass)) 
    { 
     Class* retval = new Class(*static_cast<Class*>(b)); 
     retval->name_id = (*a)->name_id; 
     *a = retval; 
    } 
    else 
    { 
     Class* retval = new Class(*b); 
     *a = retval; 
    } 
    return retval; 
} 

int main() 
{ 
    Set<int> *a = new Set<int>(1, 2, 3); 
    SetBase<int> *b = new SetBase<int>(4, 5); 
    cout << join(&a, b)->first << " " << join(&a, b)->second << " " << join(&a, b)->name_id << "\n"; 
    cout << a->first << " " << a->second << " " << a->name_id << "\n"; 

    return 0; 
} 

SetクラスがSetBase由来公開されているので、私が使用したキャストは有効である

+0

これはjoin()に渡すときには機能しませんSubSetClass –

0

TからTへの変換(またはTから派生し、実際にメンバーが設定されている情報を持ついくつかのクラス)を実装し、Tの点でjoin()関数を実装します。これは実際にテンプレートマジックのための良い場所です