Boost logo

Boost Users :

Subject: Re: [Boost-users] [Proto] lambda functions with named variables
From: Eric Niebler (eric_at_[hidden])
Date: 2010-11-02 00:16:25


On 11/1/2010 12:59 PM, Manjunath Kudlur wrote:
>>
>> 2) To provide a map-like container in which I can store things like boost::any objects. OK, maybe this is not for Proto to address but though it might still have something to offer...
>>
>
> Have you checked out Boost.Fusion map or vector for this purpose?

Second this. You do *not* want to use boost::any for this as you will
lose all type safety and optimization opportunities. Here's the basic
strategy:

Define tags like this:

    template<typename T>
    struct arg_ { typedef T type; };

    template<typename T>
    struct arg
      : proto::terminal<arg_<T> >
    {};

    struct x_ {};
    struct y_ {};

    arg<x_>::type const x = {{}};
    arg<y_>::type const y = {{}};

Now you have placeholders named x and y to play with. Now this:

    lam(x, y)

should return some object that:

1) Has a member typedef for mpl::vector<x_, y_>
2) Has an operator() member that accepts a Proto expression

The operator() in (2) above should return an object that:

1) Holds the Proto expression (by reference)
2) Has the mpl::vector of tags as a member typedef
3) Has an operator() member that accepts arguments for the lambda

The operator() in (3) above should have the same arity as the
mpl::vector of tags. It should take the arguments and put them in a
fusion::vector. Then it takes the mpl::vector of tags and the
fusion::vector of arguments and turn it into a fusion::map. This map
will be used as the state parameter when evaluating the Proto expression
(along with the map) with the following Proto algorithm:

    struct at_key : proto::callable
    {
        template<typename Sig>
        struct result;

        template<typename This, typename Map, typename Key>
        struct result<This(Map, Key)>
          : fusion::result_of::at_key<
                typename boost::remove_reference<Map>::type
              , typename boost::remove_const<
                    typename boost::remove_reference<Key>::type
>::type
>
        {};

        template<typename Map, typename Key>
        typename fusion::result_of::at_key<Map, Key>::type
        operator()(Map & map, Key const &) const
        {
            return fusion::at_key<Key>(map);
        }
    };

    struct LambdaEval
      : proto::or_<
            proto::when<
                proto::terminal<arg_<_> >
              , at_key(proto::_state, mpl::deref<proto::_value>())
>
          , proto::_default<LambdaEval>
>
    {};

Have fun!

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net