// (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
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