Editing CPPTM Answers - Exercise 3-6
BOOST WIKI
|
RecentChanges
|
Preferences
|
Page List
|
Links List
// (by Ariel Badichi) #include <boost/static_assert.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/plus.hpp> #include <boost/mpl/lambda.hpp> namespace mpl = boost::mpl; using namespace mpl::placeholders; struct twice_lambda { template<typename F, typename X> struct apply : mpl::apply<F, typename mpl::apply<F, X>::type> {}; }; int main() { typedef mpl::int_<5>::type five; typedef mpl::plus<_1, _1> unary_plus; BOOST_STATIC_ASSERT((mpl::apply<twice_lambda, unary_plus, five>::type::value == 20)); return 0; } ---- I tried to solve this problem using placeholder expressions, and ran into a surprise (for me at least). The following code works, as I had hoped: #include <boost/mpl/apply.hpp> #include <boost/mpl/lambda.hpp> #include <boost/type_traits/add_pointer.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/static_assert.hpp> #include <boost/mpl/placeholders.hpp> namespace mpl=boost::mpl; using namespace mpl::placeholders; struct add_ptr_f { template <class T> struct apply: boost::add_pointer<T>{}; }; template <class F, class X> struct apply1 : F::template apply<X> { }; int main() { BOOST_STATIC_ASSERT((boost::is_same< mpl::apply< mpl::lambda<apply1<_1,apply1<_1,_2> > >, add_ptr_f, int>::type, int**>::value )); } However, when I try to use boost::mpl::apply instead of apply1, I get some nifty errors. Even if I only try to use mpl::apply once, as in BOOST_STATIC_ASSERT((boost::is_same< mpl::apply< mpl::lambda<mpl::apply<_1,_2> >, add_ptr_f, int>::type, int*>::value )); then gcc3.4 spits out the following errors (first 2 only): /usr/local/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:49: error: no class template named `apply' in `struct boost::mpl::lambda<boost::mpl::apply<mpl_::_1, mpl_::_2, mpl_::na, ...>' 3-6.C:39: error: `type' is not a member of `boost::mpl::apply<boost::mpl::lambda<boost::mpl::apply<mpl_::_1, mpl_::_2, mpl_::na, ...>' I'm confused as to why that doesn't work. Can anyone enlighten me? --mahall ------------------------------------------------------------------------- the problem is that you didn't use "::type" for nested "mpl::apply<...>" so, we receive: BOOST_STATIC_ASSERT(( boost::is_same< mpl::apply<mpl::lambda<mpl::apply<_1, _2>::type>, add_ptr_f, int>::type, int* >::value )); the bad news is that it can be compiled but doesn't work as expected, the result is "int", not "int*". I think the reason is placeholders substitution time but cannot explain why. Really, using handmade apply1 works well because can be used w/o "::type". Try BOOST_STATIC_ASSERT(( boost::is_same< mpl::apply<mpl::lambda<mpl::apply<_1, _2>::type>, add_ptr_f, int>::type, int* >::value )); It doesn't work for the same reason that the previous example. So what is the difference between apply1 and mpl::apply and why if they are so similar, apply1 can be used w/o "::type" and mpl::apply cannot be? Because mpl::apply is partial template specialization. Details? I don't know, really. As result, following version: typedef mpl::lambda< mpl::apply< mpl::_1, mpl::apply<_1, _2>::type >::type >::type twice; BOOST_MPL_ASSERT((boost::is_same<mpl::apply<twice, boost::add_pointer<_>, int>::type, int**>)); doesn't work. Another working solution I've received looks like: BOOST_MPL_ASSERT(( boost::is_same< mpl::apply< boost::add_pointer<_>, mpl::apply<boost::add_pointer<_>, int>::type >::type, int** > )); but doesn't allow to separate "boost::add_pointer<_>". Andriy Tylychko, telya at mail dot ru -------------------------------------------------------------------------
Summary:
This change is a minor edit.
(Visit
Preferences
to set your user name.)
View other revisions
BOOST WIKI
|
RecentChanges
|
Preferences
|
Page List
|
Links List
Disclaimer: This site not officially maintained by Boost Developers