[Home]CPPTM Answers - Exercise 3-4

BOOST WIKI | RecentChanges | Preferences | Page List | Links List

Showing revision 7
 // (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 when the outer twice invokes it. - Ariel


BOOST WIKI | RecentChanges | Preferences | Page List | Links List
Edit revision 7 of this page | View other revisions | View current revision
Edited March 31, 2005 3:44 pm (diff)
Search:
Disclaimer: This site not officially maintained by Boost Developers