2011-09-08 8 views
9

次の構造を持つクラスのセットがあります。どのように型のリストから継承し、継承されたメンバのリストでメンバを呼び出すのですか?

class U 
{ 
public: 
    explicit U(int) { ... } 
    U() {...} 
    Init(int) {...} 
}; 

これらのクラスの1つ以上をクラスXに作成する必要があります。 mplがたくさん必要ですが、私はそれを本当によくしていません。私は何をしようとしていますか?コードサンプルは素晴らしいでしょう。

私のFAULT:私はC++ 11の機能を使うことはできません。私はMPLソリューションを探しています。

+0

1良い質問を。途中でミックスインを聞いたことがありますか?たぶん、それはここに適用することができますか、それの変形ですか? – Nawaz

+0

私はこれまで[Boost.MPL](http://www.boost.org/libs/mpl/)でこれまでにしたことがありますが、コードは手軽にできません。今すぐ完全な答え。誰も今までに答えなかったら、今夜私はこれを見直します。ヒントとして、テンプレート引数として2つの 'boost :: mpl :: vector <> 'イテレータを取る特別なミックスインを思い出しています。 – ildjarn

+0

UはどのようにTypeSequenceに関連していますか? –

答えて

5

まあ、Boost.MPLには、メタ機能が含まれています。inheritinherit_linearlyfor_eachと組み合わせて、(init関数を使用して)2番目のバリアントを得ることができます。

#include <iostream> 
#include <boost/mpl/fold.hpp> 
#include <boost/mpl/vector.hpp> 

struct A 
{ 
    A(int x) { std::cout << "A::A " << x << std::endl; } 
}; 

struct B 
{ 
    B(int x) { std::cout << "B::B " << x << std::endl; } 
}; 

struct C 
{ 
    C(int x) { std::cout << "C::C " << x << std::endl; } 
}; 

int main() 
{ 
    InheritFrom_IntConstructor< boost::mpl::vector<A, B, C> >(1); 
} 

メタ関数InheritFrom_IntConstructorは、コンストラクタのパラメータとして任意のタイプを受け入れるように一般化することができ、一般缶は、任意の数を受け入れることならば、私はよく分からない:

struct Null_IntConstructor 
{ 
    Null_IntConstructor(int) { } 
}; 

struct InheritFrom_IntConstructor_Folder 
{ 
    template<typename T1, typename T2> 
    struct apply 
    { 
    struct type : T1, T2 
    { 
     type(int x) : T1(x), T2(x) { } 
    }; 
    }; 
}; 

template<typename Bases> 
struct InheritFrom_IntConstructor 
    : boost::mpl::fold<Bases, 
        Null_IntConstructor, 
        InheritFrom_IntConstructor_Folder>::type 
{ 
    InheritFrom_IntConstructor(int x) 
    : boost::mpl::fold<Bases, 
         Null_IntConstructor, 
         InheritFrom_IntConstructor_Folder>::type(x) 
    { } 
}; 

使用例:それともboost::mpl::foldとカスタムメタ関数を使用して議論

+0

+1:テスト中です。:) –

+0

@ビーゴス:完璧に動作します。私は正確に '折りたたみ'が何をしているのかを調べる必要がありますが、非常にありがとう! –

+0

@Armen: 'mpl :: fold'は私のソリューションでやったこととほぼ同じです。 – Nawaz

1

何か作業をする必要があります:

template<class typeOne> 
class X1 : public typeOne 
{ 
    X(int b): typeOne(b) 
    {} 
}; 
template<class typeOne, class typeTwo> 
class X2 : public typeOne, public typeTwo 
{ 
    X(int b): typeOne(b), typeTwo(b) 
    {} 
}; 
template<class typeOne, class typeTwo, class TypeThree> 
class X3 : public typeOne, public typeTwo, public typeThree 
{ 
    X(int b): typeOne(b), typeTwo(b), typeThree(b) 
    {} 
}; 

か、あなたがオブジェクトごとに数バイトを無駄に喜んでいる場合は、プレースホルダを使用し、唯一の大規模なものを作ることができます。これは、インスタンスごとに使用されていない基本タイプごとに最大で1バイトを無駄にするはずです。

template<int> 
class PlaceHolder { PlaceHolder(int){} }; 

template< 
     class typeOne, 
     class typeTwo=PlaceHolder<2>, 
     class TypeThree=PlaceHolder<3>, 
     class TypeFour=PlaceHolder<4>, 
     class TypeFive=PlaceHolder<5> 
     > 
class X : 
     public typeOne, 
     public typeTwo, 
     public typeThree, 
     public typeFour, 
     public typeFive 
{ 
    X(int b) 
    : typeOne(b), 
    typeTwo(b), 
    typeThree(b), 
    typeFour(b), 
    typeFive(b) 
    {} 

    X(const X& b) 
    : typeOne(b), 
    typeTwo(b), 
    typeThree(b), 
    typeFour(b), 
    typeFive(b) 
    {} 

    X& operator=(const X& b) { 
     typeOne::operator=(b); 
     typeTwo::operator=(b); 
     typeThree::operator=(b); 
     typeFour::operator=(b); 
     typeFive::operator=(b);} 
     return *this; 
    } 
}; 
+0

異なるテンプレート引数を持つ同じテンプレートを持つことはできません数字 –

+0

が正しく、テンプレート名が変更され、1つの名前でしか動作しないが、スペースを無駄にする可能性があるバージョンを追加しました。 –

+1

私は正直なところあなたの解決策が嫌いですが、あなたが私を助けようと時間を費やしたので私はそれを上書きしています。ありがとう –

3

これはなんですか?

template <typename ...BaseClasses> 
class Aggregator : public BaseClasses... 
{ 
public: 
    Aggregator(int i) : BaseClasses(i)... 
    {} 

}; 

使用例:

Aggregator<U, V, W> a(10); 
Aggregator<U, V> b(15); 
Aggregator<W> c(20); 

注:可変長テンプレートを使用するため、C++ 11が必要です。

+2

+1:これはきれいでシンプルなsooooです。ありがとうございました。残念ながら、***不思議な***私はバリデーショナルなテンプレートを使用することはできません:( –

+0

'BaseClasses(i)...'それは動作しますか?14.5.3/5はそれを読むようです!ニート! –

+0

C + +11表現力。元の質問を任意の数の任意のタイプのコンストラクタ引数に一般化したい。 – Begemoth

2

私はBoostを使用していないので、私の解決策がどれだけ必要なものに近いか分かりません。コードをテストし、その後、

template<typename typeseq> 
struct X : typeseq::head, X<typename typeseq::tail> 
{ 
    typedef typename typeseq::head base; 
    typedef X<typename typeseq::tail> recursebase; 
    X(int i) : base(i), recursebase(i) {} 
    void init(int i) 
    { 
     base::init(i); 
     recursebase::init(i); 
    } 
}; 

template<> 
struct X<null_type> 
{ 
    X(int i) {} 
    void init(int i) { } 
}; 

をそして:しかし、まだ、私はそれを掲示しています

typedef typelist<S,typelist<U>> typeseq; 
X<typeseq> x(10); 
x.init(100); 

オンラインデモ:http://ideone.com/e6tuM

+0

いい仕事ですが、mplを再利用するのはきれいであることを認めています:) –

+0

Begemothの答えを見たとき、これも私に起こり、私はそれを投稿しようとしていました。あなたはもっと速かったです:私のオリジナルよりもD Wayの方がより良い答えです。 –

関連する問題