|
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