2011-09-08 58 views
9

我有一組具有以下結構類:如何從類型列表繼承,然後在繼承成員列表中調用成員?

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

我需要能夠撰寫1以上這些類爲類X.僞代碼:

template<class TypeSequence> 
class X that derives publicly from all the classes in TypeSequence 
{ 
    X(int): all bases are initialized with the integer passed 
    {} 
    //if the above constructor is impossible, then the following will do as well: 
    X(int) 
    { 
     Call Init on all bases and pass the given int to them. 
    } 
}; 

我想我需要很多mpl,但我並不擅長。我想要做什麼?代碼示例會很棒。

我的錯誤:忘了提及我不能使用C++ 11功能。我正在尋找MPL解決方案。

+0

+1問得好。你聽說過mixin的方式嗎?也許,它可以適用於此,或它的變體? – Nawaz

+0

我之前用[Boost.MPL](http://www.boost.org/libs/mpl/)完成了這個操作,但我沒有代碼,並且沒有時間寫一個現在完整回答。如果到那時還沒有人回答,我今晚會重新回顧一下。作爲一個提示,我記得做了一個特殊的mixin,它將兩個'boost :: mpl :: vector <>'迭代器作爲模板參數。 – ildjarn

+0

U與TypeSequence有什麼關係? –

回答

5

那麼,Boost.MPL包含的元函數inheritinherit_linearly你可以將它們與for_each組合起來得到第二個變體(帶有init函數)。或者只使用boost::mpl::fold和自定義的元函數:

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) 
    { } 
}; 

用例:

#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可推廣到任意接受類型作爲構造函數的參數,我不知道是否能推廣到接受任意數量參數。

+0

+1:正在測試.. :) –

+0

@Begeoth:完美地工作。我需要看看究竟是什麼「摺疊」,但非常感謝你! –

+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) 
    {} 
}; 

,或者,如果你願意浪費每個對象的幾個字節,你可以使用一個佔位符,只有成爲一個大。這應該浪費每個實例每個未使用的基本類型最多一個字節。

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

我誠實地不喜歡你的解決方案,但我贊成它,因爲你花時間來試圖幫助我。謝謝 –

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:這太簡潔了。謝謝。不幸的是,***不幸的是***我不能使用可變參數模板:( –

+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比我的原稿更好。 –