
On 3/20/07, Giovanni Piero Deretta <gpderetta@gmail.com> wrote:
On 3/20/07, Daniel Walker <daniel.j.walker@gmail.com> wrote:
On 3/20/07, Eric Niebler <eric@boost-consulting.com> wrote:
If lambda functors had both sig<> and result<> nested templates, then it would Just Work without causing any back-compat problems.
That's true, but I was concerned about funtors defined by lambda users.
What about doing both? Result_of would implement (maybe undocumented and deprecated) sig support. Lambda would implement and document both result and sig, deprecating the latter. In a release or two, both lambda and result_of would drop sig support. The users should have plenty of time for updating their code.
That sounds like a good idea to me. I was just looking into adding result<> support to Lambda, and I think it's fairly strait forward. I came up with the following preprocessor metafunction to help things along, and I believe it could have a general use for folks writing result_of compatible functors. I'm not sure if it should be included in a library someplace, perhaps result_of. I imagine this would help Fusion provide support for result_of style result. // Expands to partial specializations of an argument dependent nested // result<> type generator for functors with variable arity. // first - the lower bound of the functor arity. // last - the upper bound of the functor arity. // macro - a unary operation of the form macro(n) where n is the // current arity of the function. This macro is used as the // definition of result<>::type like so: // typedef macro(n) type; BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE(first, last, macro) It would be easy to define another macro BOOST_FIXED_ARITY_FUNCTOR_RESULT_TYPE for when you don't want partial specializations of result<> for multiple numbers of arguments to the functor. The implementation looks like this. #define BOOST_RESULT_TYPE_PARTIAL_SPECIALIZATIONS(z, n, macro) \ template < \ class F \ BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) \ > \ struct result<F(BOOST_PP_ENUM_PARAMS(n, A))> { \ typedef macro(n) type; \ }; \ /**/ #define BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE(first, last, macro) \ template <class F> struct result; \ BOOST_PP_REPEAT_FROM_TO( \ first, last \ , BOOST_RESULT_TYPE_PARTIAL_SPECIALIZATIONS \ , macro \ ) \ /**/ Here's how I used it in lambda::lambda_functor<>. #define BOOST_LAMBDA_FUNCTOR_NULL_RESULT_TYPE(n) \ typename F::nullary_return_type \ /**/ #define BOOST_LAMBDA_FUNCTOR_NARY_RESULT_TYPE(n) \ typename sig<tuple<BOOST_PP_ENUM_PARAMS(n, A)> >::type \ /**/ #define BOOST_LAMBDA_FUNCTOR_RESULT_TYPE(n) \ BOOST_PP_IF( \ n \ , BOOST_LAMBDA_FUNCTOR_NARY_RESULT_TYPE \ , BOOST_LAMBDA_FUNCTOR_NULL_RESULT_TYPE \ )(n) \ /**/ BOOST_VARIABLE_ARITY_FUNCTOR_RESULT_TYPE( 0 , BOOST_PP_INC(BOOST_RESULT_OF_NUM_ARGS) , BOOST_LAMBDA_FUNCTOR_RESULT_TYPE ) It expands to something like ... template <class F> struct result; template < class F > struct result<F()> { typedef typename F::nullary_return_type type; }; template < class F , class A0 > struct result<F( A0)> { typedef typename sig<tuple< A0> >::type type; }; template < class F , class A0 , class A1 > struct result<F( A0 , A1)> { typedef typename sig<tuple< A0 , A1> >::type type; }; When I submit the lambda patch, should I make this macro internal to the lambda library or expose it to the public in some other library? If it should be exposed where do you think a good home for it would be? Daniel