|
Boost : |
From: Arkadiy Vertleyb (vertleyb_at_[hidden])
Date: 2003-11-28 18:43:09
Hi David,
Thanks for your reply and for the link to the archive.
>>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>
>> {};
>> };
OK, now I understand.
>>> 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.
Actualy I meant using select1st in lambda expressions that are passed to
algorithms... From your explanation, select1st<> with no parameters is a
metafunction class that gets the "first" typedef from the type passed. But
what if we have to use it in a combination with something else, say in
iter_fold. We don't have the type there -- we have an iterator. So, in
this case we can't use select1st<> with default parameter -- we have to
supply the parameter, something like:
select1st<deref<_1> >
And this again will complain about lack of "first" typedef in deref (in
VC6.5)
>>> 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?
Actually it's not just identity -- it adds "first" typedef. This is the
purpose of it -- add the typedef to satisfy VC6 without changing anything
else...
>>> 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?
I will not use my workaround unless the authors of MPL approve it. I
wouldn't like to hack MPL, and my understanding of the subject is far from
perfect. But then, how do I workaround the problem in a PORTABLE way,
preferably with no #ifdefs? And, if the #ifdef is necessary, which
configuration constant should be used?
Thanks for your help,
Arkadiy
-- Dave Abrahams Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost From: David Abrahams <dave <at> boost-consulting.com>Subject: Re: MPL/lambda questionNewsgroups: gmane.comp.lib.boost.develDate: Wed, 19 Nov 2003 07:25:45 +0000"Arkadiy Vertleyb" <vertleyb <at> hotmail.com> 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 _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk