|
Boost Users : |
From: David Abrahams (dave_at_[hidden])
Date: 2007-03-28 22:57:03
on Wed Mar 28 2007, Scott Meyers <usenet-AT-aristeia.com> wrote:
> JOAQUIN LOPEZ MU?Z wrote:
>> I think you want to write
>>
>> mpl::end<Constraints>::type
>
> Thanks for the suggestion, but it doesn't change the behavior of the program:
> the result of the insertion of a new element into the two-element set is a new
> set with only two elements (one of the original elements is lost). Please try
> it and see if you get the same thing I do.
Scott, I hate to say this, but I really think your first problem
demonstrated that mpl::set is too broken to use. I've asked Aleksey
to look at it, but he's not answering (maybe on vacation, I dunno).
I'd like to fix it myself as I was the one who came up with the basic
mechanisms for mpl::set, but unfortunately I can't tell what Aleksey
intended in his realization of those ideas so I'm not quite sure where
to start. You might see if you can use mpl::map to do the same things.
>> Well, excuse me if the following is obvious to you,
>> but ::type is to a metafunction what actual invocation is
>> to a run-time function. So, mpl::end<Constraints> refers
>> to the name of the entity, but does not actually compute
>> its "return value" unless you add the ::type suffix.
>
> I don't think this always holds.
Yeah, it always holds.
> For example, I don't need to add the ::type
> suffix when I make a typedef or when I do an assertion:
>
> typedef mpl::set<A, B> MySet;
There's no metafunction invocation there; you're just stating the name
ofa type (mpl::set<A,B>). mpl::set<...> may actually have a ::type
member (essentially a typedef for mpl::set<...> itself), but if so
it's just there as a convenience for use with constructs like eval_if.
mpl::eval_if<
predicate
, some_metafunction_to_be_evaluated_if_pred_true<X>
, mpl::set< ... >
>
it prevents you from having to write
mpl::eval_if<
predicate
, some_metafunction_to_be_evaluated_if_pred_true<X>
, mpl::identity<mpl::set< ... > >
^^^^^^^^^^^^^
>
> BOOST_MPL_ASSERT(( mpl::equal<mpl::set<A,B>, mpl::set<A,B> > ));
No explicit metafunction invocation there either... at least, not by
you. Again, you're just stating the name of a type:
mpl::equal<mpl::set<A,B>, mpl::set<A,B> >
That type happens to be a nullary metafunction (any N-ary
metafunction, where N>0, with all its arguments filled in, is a
nullary metafunction: a class with a nested ::type). Actually the
extra set of parens is used by MPL to form a function type:
int (mpl::equal<mpl::set<A,B>, mpl::set<A,B> >)
MPL strips the int(...) off to get your nullary metafunction, and then
it invokes that. Just as with the 2nd or 3rd argument to mpl::eval_if.
There's a class of metafunctions that usually don't need to be
explicitly invoked: those whose range of results is limited in certain
ways. In practice this turns out to mean metafunctions with
numeric/boolean results. For example, I could write a
metafunction to square a numeric value like this:
template <class N>
struct square
: mpl::integral_c<
N::value_type, N::type::value*N::type::value
>
{};
In what sense is that a metafunction? Well, all MPL IntegralConstants
contain a nested ::type returning an equivalent IntegralConstant. So
integral_c looks like:
template <class T, T x>
struct integral_c
{
typedef T value_type;
static T const value = x;
typedef integral_c<T,x> type;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
};
So integral_c<U,v> is a self-returning nullary metafunction (reach
inside to get its ::type, you get itself back). And square<X>
inherits most of those properties... enough to make it a conforming
IntegralConstant.
As a result, you could write
mpl::add< square<mpl::int_<3> >::type, mpl::int_<1> >::type
^^^^^^
or
mpl::add< square<mpl::int_<3> >, mpl::int_<1> >::type
and you'd get the same result. The same applies to all the Boost/TR1 type
traits with their boolean result types. That's why you can write either:
mpl::if_<
boost::is_pointer<X>::type
, T // ^^^^^^
, F
>::type
or
mpl::if_<
boost::is_pointer<X> // no ::type
, T
, F
>::type
and get the same result.
Incidentally, it's possible to construct a C++ template
metaprogramming system in which ::type (and typename!) is needed much
less frequently
(http://aspn.activestate.com/ASPN/Mail/Message/boost/2259201). I
think Vesa's approach had a lot of promise and I wish we'd had time to
pursue it.
-- Dave Abrahams Boost Consulting www.boost-consulting.com Don't Miss BoostCon 2007! ==> http://www.boostcon.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net