我有一个类的功能,我想依赖于一组插件策略。但是,我不确定如何从一个任意数量的类派生一个类。
下面的代码是我想要实现的一个例子。
// 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
答案 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;
}