Arises from an arbitrary number of classes

I have a class whose functionality I would like to depend on a set of plugins. But I'm not sure how to get the class to get an arbitrary number of classes.

Below is an example of what I am trying to achieve.

// 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;
}

      

Thanks, PaulH

+2


source to share


3 answers


With Boost.MPL Library :

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

      

Used like:



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

      

For the "OR-all all MY_IDENTIFIER" part, something like the following lines:

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

      

+6


source


To get from an arbitrary list of types, you will need to specify an arbitrary number of types. For this, I only know type lists. I will use this for the following code:

class nil {};

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

      

With this in mind, you can create a template that infers from all types in the type list:

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

      

I have tested this with the following code



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

      

Both VC and Comeau seem to be like this code and it prints

A
B
C

      

so it works.

+4


source


Possible implementation using type lists:

#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;
}

      

0


source







All Articles