|
Boost : |
From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2003-11-01 04:24:01
Sebastian Faust wrote:
> Hi,
Hi Sebastian,
> I wanna develope an factory class template which takes as template
argument
> a typelist and creates me then iterative objects of the types in the
> typelist. The different objects will be connected ( like in the chain of
> responsibility pattern ), so that after the creation process I only will
get
> back one pointer to the beginning object of the chain.
> I read about the boost::mpl -library and was very impressed, sadly I am
> absolutly new to metaprogramming so I really have some problems to solve
my
> problem, so I really would be thankful for any help.
>
> To show my problem I give a standard example about what I wanna do:
>
> class vehicle
> {
> public:
> vehicle(vehicle* successor) : m_successor(successor) {}
> virtual vehicle* create(vehicle* successor) = 0;
> vehicle* m_successor;
>
> };
> class car : public vehicle
> {
> public:
> car(car* successor) : vehicle(successor) {}
^^^^
I assume here and in other constructors below you meant 'vehicle*'.
> virtual vehicle* create(vehicle* successor)
> {
> return new car(successor);
> }
> };
>
> class bicycle : public vehicle
> {
> public:
> bicycle (bicycle * successor) : vehicle(successor) {}
> virtual vehicle* create(vehicle* successor)
> {
> return new bicycle (successor);
> }
> };
>
> class train : public vehicle
> {
> public:
> train (train * successor) : vehicle(successor) {}
> virtual vehicle* create(vehicle* successor)
> {
> return new train (successor);
> }
> };
>
> With the help of some from the ACCU mailinglist I could find out to use
the
> for_each template to iterate over a boost::mpl::list, but how can I get
the
> returned value from the method create?
So, IIUYC, you want to generate something along the following lines:
vehicle* make(vehicle* v0)
{
vehicle* v1 = new car( v0 );
vehicle* v2 = new bicycle( v1 );
vehicle* v3 = new train( v2 );
return v3;
}
?
The simplest way would be something like this:
namespace mpl = boost::mpl;
using namespace mpl::placeholders;
struct pass_through_make
{
static vehicle* make( vehicle* ptr )
{
return ptr;
}
};
template< typename T, typename Base > struct make_vehicle
{
static vehicle* make( vehicle* ptr )
{
return new T( Base::make( ptr ) );
}
};
typedef mpl::fold<
mpl::vector<car,bicycle,train>
, pass_through_make
, make_vehicle<_2,_1>
>::type factory;
int main()
{
factory::make( 0 );
return 0;
}
Basically, the above is equivalent to
typedef make_vehicle<train
, make_vehicle<bicycle
, make_vehicle<car
, pass_through_make
> > > factory;
int main()
{
factory::make( 0 );
return 0;
}
See the docs for 'fold' (http://tinyurl.com/t8f5) for more information.
<digression>
Of course ideally Fusion and MPL should interpolate so that the above could
be written as
struct make_vehicle
{
template< typename T > struct result
{
typedef vehicle* type;
};
template< typename T >
vehicle* operator()(identity<T>, vehicle* ptr) const
{
return new T(ptr);
}
};
int main()
{
vehicle* result = fusion::fold(
fusion::identity_view< mpl::vector<vehicle,car,bicycle,train>
>()
, static_cast<vehicle*>(0)
, make_vehicle
);
return 0;
}
</digression>
HTH,
Aleksey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk