Boost logo

Boost :

From: Joel de Guzman (joel_at_[hidden])
Date: 2003-11-02 23:56:52


Aleksey Gurtovoy <agurtovoy_at_[hidden]> wrote:

>>> 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>
>>
>> I'm not sure why that's an improvement.
>
> IMO the way the OP problem is formulated, it literally screams for
> 'fold'/'accumulate':
>
>> vehicle* make(vehicle* v0)
>> {
>> vehicle* v1 = new car( v0 );
>> vehicle* v2 = new bicycle( v1 );
>> vehicle* v3 = new train( v2 );
>> return v3;
>> }
>
> And then the 'fold' version requires less code on the user side.
>
>> Is identity_view supposed to
>> default-construct a vehicle,car, bicycle, and train?
>
> Nope, it constructs 'identity<vehicle>', 'identity<car>', etc.

Very nice! And it is doable now. Apart from identity_view, we have
all the necessary ingredients now. identity_view is quite simple.
It is just mpl::transform<s, mpl::identity<_> >, I'm not sure if
it's worthy to be included into the library. Here's the actual syntax:
(untested):

    typedef mpl::vector<vehicle,car,bicycle,train> vec;
    typedef mpl::transform<s, mpl::identity<_> > ivec;
    fusion::type_sequence<ivec> view;
    vehicle* result = fusion::fold(view, static_cast<vehicle*>(0), make_vehicle);

I think it is possible to work directly on mpl sequences. So, the syntax
might be simplified to:

    typedef mpl::vector<vehicle,car,bicycle,train> vec;
    typedef mpl::transform<s, mpl::identity<_> > ivec;
    vehicle* result = fusion::fold(ivec(), static_cast<vehicle*>(0), make_vehicle);

Or, if you rig make_vehicle as:

    struct make_vehicle
    {
        template< typename T > struct result
        {
            typedef vehicle* type;
        };

        template< typename T >
        vehicle* operator()(T*, vehicle* ptr) const
        {
            return new T(ptr);
        }
    };

you don't need the identity, so you can further simplify:

    typedef mpl::vector<vehicle*,car*,bicycle*,train*> vec;
    vehicle* result = fusion::fold(vec(), static_cast<vehicle*>(0), make_vehicle);

Cheers,

-- 
Joel de Guzman
http://www.boost-consulting.com
http://spirit.sf.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk