Boost logo

Boost :

From: Arkadiy Vertleyb (vertleyb_at_[hidden])
Date: 2003-11-18 21:33:57


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... which
doesn't fit here at all... But for some reason the above code DOES work on
VC6, and it works correctly!

> ... 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? And can we apply the same
form of select1st in other contexts? What do we do if anything needs to be
passed to select1st?

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;
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?

Thanks,
Arkadiy


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