派生自任意数量的类

时间:2009-10-20 21:41:35

标签: c++ templates multiple-inheritance

我有一个类的功能,我想依赖于一组插件策略。但是,我不确定如何从一个任意数量的类派生一个类。

下面的代码是我想要实现的一个例子。

// insert clever boost or template trickery here
template< class ListOfPolicies >
class CMyClass : public ListOfPolicies 
{
public:
    CMyClass()
    {
        // identifiers should be the result of OR-ing all 
        // of the MY_IDENTIFIERS in the TypeList.
        DWORD identifiers; 

        DoSomeInitialization( ..., identifiers, ... );
    }

    int MyFunction()
    {
        return 100;
    }

    // ...
};

template< class T >
class PolicyA
{
public:
    enum { MY_IDENTIFIER = 0x00000001 };

    int DoSomethingA()
    {
        T* pT = static_cast< T* >( this );
        return pT->MyFunction() + 1;
    };

    // ...
};

template< class T >
class PolicyB
{
public:
    enum { MY_IDENTIFIER = 0x00000010 };

    int DoSomethingB()
    {
        T* pT = static_cast< T* >( this );
        return pT->MyFunction() + 2;
    };

    // ...
};

int _tmain(int argc, _TCHAR* argv[])
{
    CMyClass< PolicyA > A;
    assert( A.DoSomethingA() == 101 );

    CMyClass< PolicyA, PolicyB > AB
    assert( AB.DoSomethingA() == 101 );
    assert( AB.DoSomethingB() == 102 );

    return 0;
}

谢谢, PaulH

3 个答案:

答案 0 :(得分:6)

使用Boost.MPL库:

//Warning: Untested
namespace bmpl = boost::mpl;
template<class Typelist>
class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type
{
...
};

用作:

X<bmpl::vector<Foo, Bar, Baz> > FooBarBaz;

对于“OR-ing all MY_IDENTIFIER”部分,有以下几点:

//Warning: still not tested:
enum {OR_ED_IDENTIFIERS = 
    bmpl::fold<Typelist, bmpl::int_<0>, bmpl::bitor_<_1, _2> >::value;
}

答案 1 :(得分:4)

要从任意类型列表派生,您必须列出任意数量的类型。为此,我只知道类型列表。我将使用它来代码如下:

class nil {};

template< typename H, class T >
struct type_list {
    typedef H head_type;
    typedef T tail_type;
};

鉴于此,您可以创建一个派生自类型列表中所有类型的模板:

template< class TL >
struct derivator;

template<>
struct derivator<nil> {};

template< typename H, typename T >
struct derivator< type_list<H,T> > : public H
                                   , public derivator<T> {};

我用以下代码测试了这个

class A {};   void a(A) {std::cout << "A\n";}
class B {};   void b(B) {std::cout << "B\n";}
class C {};   void c(C) {std::cout << "C\n";}

class X : public derivator< type_list<A 
                          , type_list<B 
                          , type_list<C 
                          , nil > > > > {};

int main(void)
{
    X x;
    a(x);
    b(x);
    c(x);

    return 0;
}

VC和Comeau似乎都喜欢这个代码并打印

A
B
C

所以它似乎有效。

答案 2 :(得分:0)

使用类型列表的可能实现:

#include <cstdlib>

/**
 * Base classes that you want to inherit from.
 */
struct A
{
    A() {std::cout << "A()" << std::endl;}
};

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

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

/**
 * Typelists
 */
struct NullType {};

template <typename H, typename T>
struct InheritanceList : public H, public T
{
    typedef H head_t;
    typedef T tail_t;
};

template <typename H>
struct InheritanceList<H,NullType> : public H
{
    typedef H        head_t;
    typedef NullType tail_t;
};

#define INHERITANCE_LIST_1(x)     InheritanceList<x,NullType>
#define INHERITANCE_LIST_2(x,y)   InheritanceList<x,InheritanceList<y,NullType>
#define INHERITANCE_LIST_3(x,y,z) InheritanceList<x,InheritanceList<y,InheritanceList<z,NullType> > >

/**
 * Your class
 */
struct MyClass : public INHERITANCE_LIST_3(A,B,C)
{
};

/**
 * Entry point
 */
int main( int argc, char** argv )
{
    MyClass mc;

    return EXIT_SUCCESS;
}