Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-11-19 12:25:45


"Arkadiy Vertleyb" <vertleyb_at_[hidden]> writes:

> Hi Aleksey,
>
>> > typedef mpl::vector4<
>> > mpl::pair<int, int*>,
>> > mpl::pair<short, short*>,
>> > mpl::pair<long, long*>,
>> > mpl::pair<char, char*>
>> > > pairs;
>> >
>> > typedef mpl::find_if<
>> > pairs,
>> > boost::is_same<mpl::bind1<mpl::select1st<>, mpl::_>, long> >::type
>> iter;
>>
>> Uhmm, this one doesn't work because 'mpl::bind1<mpl::select1st<>, mpl::_>'
>> (and therefore the whole predicate) is not a lambda expression; a result
> of
>> any 'bind' template instantiation is a plain metafunction class. IOW, the
>> above is pretty much equivalent to
>>
>> typedef mpl::find_if<
>> pairs,
>> boost::is_same<is_first_same_as_long, long> >::type iter;
>>
>> for which it's obvious (I hope) that it won't work as intended.
>
> It is KIND OF obvious... If I understand bind correctly, it should decrease
> the arity of a functor. So, since select1st is a unary functor (taking a
> pair), then bind1<mpl::select1st<>, _> has to be a nullary one...

Nope, it's the same as writing boost::bind(select1st, _1): that is,
it just creates a "function object" (a metafunction class in the
compile-time world).

>> ... but the one I would actually recommend you to use would be this:
>>
>> typedef mpl::find<
>> mpl::transform_view< pairs,mpl::select1st<> >
>> , long
>> >::type::base iter;
>
> Now I am totaly confused.... how does THIS work?

select1st is defined with default arguments, and then specialized so
that when the defaults are used you have a metafunction class:

     template <class P = _>
     struct select1st
     {
        typedef ... type; // whatever
     };

     template <>
     struct select1st<_>
     {
        template <class P>
        struct apply : select1st<P>
        {};
     };

> And can we apply the same form of select1st in other contexts?

Yes.

> What do we do if anything needs to be passed to select1st?

Use mpl::apply.

> Meanwhile I was going to use a simple workaround that seams to work with
> find_if, transform_view, etc. (I tried it with VC6 and GCC 3.3):
>
> template<class T>
> struct fake1st : T
> {
> typedef int first;
> typedef T type;
> };
>
> main()
> {
> typedef mpl::vector<
> mpl::pair<char, char*>,
> mpl::pair<long, long*>,
> mpl::pair<int, int*>
> > pairs;
>
> // works with transform_view, too
>
> typedef mpl::find_if<
> pairs,
> boost::is_same<mpl::select1st<fake1st<mpl::_1> >, int>
> >::type it;
>
> typedef mpl::select2nd<mpl::deref<it>::type>::type type;
> BOOST_MPL_ASSERT_IS_SAME(type, int*);
>
> return 0;
> }
>
> If I understand things correctly, this should work with both approaches:
>
> 1. On a deficient compiler, fake1st<_1>::apply<...> means _1::apply<...>,
> since it is inherited;

  _1::apply<X>::type

is just

   X

So I don't think this does what you want. But then fake1st is also
just the identity metafunction, so if that's all you want why not
just use mpl::identity?

> 2. On a conforming compiler fake1st will be (like any template)
> lambda-enabled, so
>
> apply<fake1st<_1>, ...>::type
>
> should boil down to
>
> fake1st<apply<_1, ...>::type>::type
>
> which is (due to the second typedef in fake1st):
>
> apply<_1, ...>::type
>
> What do you think about this?

Why jump through hoops?

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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