[lambda][utility] patch to make lambda compatible with result_of

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

Hello, It was pointed out to me in another thread (http://tinyurl.com/2l22av) that the following is an incorrect usage of result_of. On 3/21/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
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; } };
[...]
template<class F, class Arg> typename result_of<F(F, Arg)>::type f(F const& functor, Arg& a) { return functor(a); }
[...]
result_of< sig_functor(sig_functor, value_type) >::type z = f(sig_f, x);
The result of documentation states: "Given an lvalue f of type F and lvalues t1, t2, ..., tN of types T1, T2, ..., TN, respectively, the type result_of<F(T1, T2, ..., TN)>::type defines the result type of the expression f(t1, t2, ...,tN)." So, obviously the usage above is wrong. The reason it compiled (using gcc 4.1) was due to a misunderstanding I had in converting result<> to sig<> and vice versa. I did ... sig<tuple<F, T1, T2, ..., TN> > <--> result<F(F, T1, T2, ..., TN)> It should have been. sig<tuple<F, T1, T2, ..., TN> > <--> result<F(T1, T2, ..., TN)> The attached patch is a revision of the first that corrects this problem. Also, I added a check for the availability of result_of through BOOST_NO_RESULT_OF and left the behavior unchanged for platforms that result_of doesn't support. With this revised patch you can do. #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(A0)>::type is A0. BOOST_FIXED_ARITY_FUNCTOR_RESULT(1, A0) template<class Arg> typename result<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(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); } And additionally with my previously submited result_of patch ... result_of< sig_functor(value_type) >::type z = f(sig_f, x); I ran the lambda regressions again and they passed. Let me know if you see more problems. Thanks! Daniel
participants (1)
-
Daniel Walker