I have a decorator-like pattern with a base that requires a constructor parameter. The decorator is constructed such that it can take an arbitrary number of add-on components as template parameters (up to 3 in this example).
Unfortunately, I can't figure out how to pass the base's constructor parameter to it when more than one add-on is specified. In the example below, CMyClass< AddOn_A > A( 100 );
works perfectly, but CMyClass< AddOn_A, AddOn_B > AB( 100 );
generates an error at the CMyClass constructor.
template< class Base >
class AddOn_A : public Base
{
public:
AddOn_A( int x ) : Base( x )
{
};
int AddOne()
{
return static_cast< Base* >( this )->DoSomething() + 1;
};
};
template< class Base >
class AddOn_B : public Base
{
public:
AddOn_B( int x ) : Base( x )
{
};
int AddTwo()
{
return static_cast< Base* >( this )->DoSomething() + 2;
};
};
class CBase
{
public:
explicit CBase( int x ) : x_( x )
{
};
int DoSomething()
{
return x_;
};
private:
int x_;
};
// define an empty AddOn
template< class > class empty {};
// forward declaration and Add-On defaults
template< template< class > class AddOn1 = empty,
template< class > class AddOn2 = empty,
template< class > class AddOn3 = empty >
class CMyClass;
// specialized template for the default case
template<> class CMyClass< empty, empty, empty > {};
// actual definition
template< template< class > class AddOn1,
template< class > class AddOn2,
template< class > class AddOn3 >
class CMyClass : public AddOn1< CBase >,
public CMyClass< AddOn2, AddOn3 >
{
public:
// what needs to go here???
CMyClass( int x ) : AddOn1< CBase >( x )
{};
};
int _tmain( int argc, _TCHAR* argv[] )
{
// works
CMyClass< AddOn_A > A( 100 );
_ASSERT( A.AddOne() == 101 );
// works
CMyClass< AddOn_B > B( 100 );
_ASSERT( B.AddTwo() == 102 );
// generates an error at the CMyClass ctor:
// error C2512: 'CMyClass<AddOn1>' : no appropriate default constructor available
CMyClass< AddOn_A, AddOn_B > AB( 100 );
_ASSERT( AB.AddOne() == 101 );
_ASSERT( AB.AddTwo() == 102 );
return 0;
}
If anybody can point out what I may be doing wrong, please let me know.
Thanks, PaulH