|
Boost : |
From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-09-19 16:35:31
Terje Slettebø wrote:
> In the posting with my "factorial" metafunction
> (http://aspn.activestate.com/ASPN/Mail/Message/1316005), I
> propose to make the metafunctions evaluate their own arguments
> (apply "::type" to them), just like it happens in run-time functions.
> With that, the factorial example becomes (quoting from my posting):
>
> template<class V>
> struct factorial
> {
> typedef typename V::type Value;
>
> typedef typename apply_if<equal_to<Value,value<Value,0> >,
> value<Value,1>,
> mul<Value,factorial<prior<Value> > >
> >::type type;
> }
>
> The first typedef evaluates the metafunction argument, V.
>
> "value" is another new metafunction. It's a way to provide a generic
> constant, of the type given in the first argument, and the
> value given in the second. Thus, if "Value" is int_c<...>, then
> "value<Value,1>::type" is int_c<1>.
mpl::integral_c<..>?
[..]
> If the metafunctions, like plus, evaluated their own arguments, as
> suggested, you could write it like this [Addition: I see that
> you've come to this, yourself, too, later here]:
>
> apply_if< some_condition,
> some_type_1,
> plus< some_type_2, some_number >
> >::type
>
> This avoids evaluating some_type_2, unless that part of the
> if-branch is taken. Note that for this to work, all values must have
> a "type" member, which is the case in MPL. If a type isn't a
> metafunction, "type" simply provides the identity, the same type.
> So "::type" may be applied unconditionally on all types.
>
> I found that such a change of MPL would greatly simplify
> writing code for it, as you avoid having to create ad-hoc templates
> (like your "recurse", above), just to avoid premature instantiation
> (evaluation) of some_type_2.
> Thus, you can write the code in a natural way, not having to
> spread it out.
> I found this spreading out to be similar to how template
> specialisations spreads code, which is what functions like apply_if
> is meant to avoid. You also avoid all those "::type"s in the code.
I considered and re-considered the idea a couple of times during MPL
development. It doesn't really work well; in particular, it conflicts with
the notion of nullary metafunctions, pretty much making the library useless
for manipulating the latter ones:
// build a table of nullary metafunctions for later
// (selective) invocation
typedef push_back< f_table0,my_f<arg1,arg2> >::type f_table1;
typedef push_back< f_table1,her_f<arg3> >::type f_table2;
...
It's not hard to see that if 'push_back' is implemented along the lines of
the proposed idea
template<
typename Sequence
, typename T
>
struct push_back
: push_back_traits< typename BOOST_MPL_AUX_SEQUENCE_TAG(Sequence) >
::template algorithm<
typename Sequence::type // apply0<T>::type
, typename T::type // apply0<T>::type
>
{
};
the above code doesn't really work as expected - it actually _evaluates_ all
the metafunctions that were supposed to be put into the table, and stores
the invocation results instead.
Adding 'identity' there, besides being counter-intuitive, doesn't really
solve anything:
// build a table of nullary metafunctions for later
// (selective) invocation
typedef push_back< f_table0,identity< my_f<arg1,arg2> > >::type
f_table1;
typedef push_back< f_table1,identity< her_f<arg3> > >::type f_table2;
...
// filter the table
typedef copy_if<
f_table10
, push_back<_,_>
, vector<>
, is_needed
>::type f_result_table;
// opps, all copied metafunctions got invoked along the way!
That's more, it's not only unary metafunctions that become affected by the
change; basically, "passing through" of anything expect "canonical" types
such as 'int_c' becomes a source of possible surprise and troubles:
// doesn't work anymore!
// typedef list<bool,char,short,int,long> types;
// have to do this:
typedef list<
identity<bool>
, identity<char>
, identity<short>
, identity<int>
, identity<long>
> types; // ouch!
// doesn't work either!
typedef copy<
filer_view< types, less< size_of<_>, size_of<int> >
, push_back<_,_>
, vector<>
>::type filtered_types;
Well, I hope you've got the picture.
>
> Paul Mensonides replied at the time that he found this a
> sensible solution to it. However, I haven't heard anything on this
> issue from others, such as Aleksey or Dave.
That's because I am yet to read those 200+ post-review MPL-related messages
that were posted during the 3-weeks period when I was out of country :).
Aleksey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk