
Boost : 
From: David Abrahams (dave_at_[hidden])
Date: 20031119 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
compiletime 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)
> lambdaenabled, 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.boostconsulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk