2011-09-08 75 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比我的原稿更好。 –