Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2007-03-20 16:34:30


On 3/20/07, Giovanni Piero Deretta <gpderetta_at_[hidden]> wrote:
> On 3/20/07, Daniel Walker <daniel.j.walker_at_[hidden]> wrote:
> > On 3/20/07, Eric Niebler <eric_at_[hidden]> 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


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