Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-03-21 12:24:34


Hello,

Following up on Eric's suggestion in this thread,
http://tinyurl.com/yr3gc9, I have attached a patch for functors
generated by lambda expressions to expose result<F(ARGS)> in addition
to sig<tuple<ARGS> > and for lambda expressions to deduce the return
type of user defined functors that expose either. This makes the
lambda library compatible with result_of and with user defined
functors that use the result<> convention of specifying return types.
Apply the patch with 'patch -p0 < djw_lambda_result.patch' from the
boost root directory. This patch depends on the has_template_xxx patch
I submitted previously (http://tinyurl.com/35x5z5).

It was a pleasent surprise to find that the required changes are
fairly minor. I added result<> traits to lambda::lambda_functor that
simply wrap the existing sig<> trait. Following Shunsuke's suggestion,
I used a converter to allow lambda::function_adaptor::sig<> to accept
functors that use either sig<> or result<>. The patch places the
macros I mentioned (http://tinyurl.com/2za4ek) for adding nested
result<> members in result_of.hpp. That seems like as good a place as
any since they're closely related to result_of. I changed their names
a little though.

I think this patch is valuable because it alleviates some of the
incompatibilities that stem from having more than one convention for
specifying argument dependent return types. It also paves the way for
deprecating sig<> in favor of the more standard result<>. However, I
believe my previous patch (http://tinyurl.com/2h3g7n) to result_of is
still valuable as it allows result_of to handle lambda-compatible user
defined functors using the existing sig<> convention.

Either way, the attached patch allows you to do things like this.

#include <boost/lambda/bind.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility/result_of.hpp>
using namespace boost;

struct result_functor {
    // Define a result trait such that result<F(F,A1)>::type is A1.
    BOOST_FIXED_ARITY_FUNCTOR_RESULT(2, A1)

    template<class Arg>
    typename result<result_functor(result_functor, Arg)>::type
    operator()(Arg const& a) const
    {
        return a;
    }
};

struct sig_functor {
    template<class Args>
    struct sig {
        typedef typename tuples::element<1, Args>::type type;
    };

    template<class Arg>
    typename sig<tuple<sig_functor, Arg> >::type
    operator()(Arg const& a) const
    {
        return a;
    }
};

template<class F, class Arg>
typename result_of<F(F, Arg)>::type
f(F const& functor, Arg& a)
{
    return functor(a);
}

int main()
{
    using namespace boost::lambda;

    typedef char value_type;
    value_type x;
    result_functor result_f;
    value_type y = f(bind(result_f, _1), x);
    sig_functor sig_f;
    value_type z = f(bind(sig_f, _1), x);
}

My previous result_of patch would additionally allow you to do things like this.

    result_of<
        sig_functor(sig_functor, value_type)
>::type z = f(sig_f, x);

This lambda patch and the result of patch can be applied independently
or in any order.

I ran the lambda test suite and everything passed. I couldn't find a
Jamfile.v2 so I made one based on lambda's existing Jamfile. It's
included in the patch. Let me know if I've missed something or if you
know of a better way to update lambda. Of course, I can send
documentation and additional tests if there's interest.

Thanks!
Daniel




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