// (by Ariel Badichi) #include <boost/static_assert.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/add_pointer.hpp> #include <boost/mpl/apply.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/lambda.hpp>

namespace mpl = boost::mpl; using namespace mpl::placeholders;

template<typename F, typename T> struct twice : mpl::apply<F, typename mpl::apply<F, T>::type> {};

int main() { typedef mpl::lambda<boost::add_pointer<_> >::type add_pointer_lambda; typedef twice<twice<add_pointer_lambda, _>, int>::type p;

BOOST_STATIC_ASSERT((boost::is_same<int ****, p>::value));

return 0; }

Can anyone explain why the explicit lambda call is necessary? I had thought that the apply embedded in twice would deal with the add_pointer placeholder expression, but GCC 3.3.3 gives a compile error with the following:

BOOST_STATIC_ASSERT(( boost::is_same< twice< twice< boost::add_pointer<_1>, // needs to be wrapped in mpl::lambda<...>::type ??? _1 >, int >::type, int**** >::value ));

Any ideas? -- Matt Brecknell

*Section 3.3 has a nice explanation for why this won't work.* - Ariel

*Matt*: Section 3.3 does explain why versions of the *twice* metafunction from earlier sections of the book don't work directly with placeholder expressions. But then section 3.3.2 says *the first argument to mpl::apply can be any lambda expression (including those built with placeholders)*. Since your definition *twice* uses *mpl::apply* to invoke the argument metafunction, I expected to be able to use placeholder expressions without needing to use *mpl::lambda*. For example, I believe the following should work with your definition of *twice* (though I'm not in front of an MPL-capable compiler at the moment, so I can't check):

BOOST_STATIC_ASSERT(( boost::is_same< twice< boost::add_pointer<_>, // no mpl::lambda required here int >::type, int** >::value ));

I'm currently working on the theory that the problem with my version of the nested invocation of *twice* might be something to do with the way the outer *twice* is evaluating placeholders in the inner *twice*, but I haven't figured it out yet. -Matt

*In your previous snippet, consider the inner twice<> first. Consider the second argument. It's just the type _1. It's nothing special in the context of the inner twice<>. Therefore, the result of the inner twice<> is _1 **, which makes little sense for the outer twice<> (twice<_1 **, int>).* - Ariel

Disclaimer: This site not officially maintained by Boost Developers