[Home]CPPTM Answers - Exercise 4-3

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

Difference (from prior major revision) (author diff)

Added: 62a63,88
//////////////////////////////////////////////////////////////////////////////
// Adriy Tylychko (telya at mail dot ru)
// The solution above is correct but some "::type"'s don't need
// to be removed to receive the same effect, so I think version:
template< typename N1, typename N2 >
struct formula
: mpl::eval_if<
mpl::not_equal_to<N1,N2>
, typename mpl::eval_if<
mpl::greater<N1,N2>
, typename mpl::minus<N1,N2>
, N1
>::type
, typename mpl::plus<
N1
, typename mpl::times<
N1,
mpl::int_<2>
>
>
>::type
{};
// is "more correct" :)
///////////////////////////////////////////////////////////////////



 // (by Ariel Badichi)
 #include <boost/static_assert.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/mpl/apply.hpp>
 #include <boost/mpl/next.hpp>
 #include <boost/mpl/int.hpp>
 #include <boost/mpl/bool.hpp>
 #include <boost/mpl/eval_if.hpp>
 #include <boost/mpl/not_equal_to.hpp>
 #include <boost/mpl/greater.hpp>
 #include <boost/mpl/minus.hpp>
 #include <boost/mpl/plus.hpp>
 #include <boost/mpl/multiplies.hpp>

 namespace mpl = boost::mpl;

 // 4-3.1

 template<typename N, typename Predicate>
 struct next_if : mpl::eval_if<
                     mpl::apply<Predicate, N>,
                     mpl::next<N>,
                     N
                  >
 {};

 // 4-3.2

 // formula runtime pseudo-code (I used this to write the tests)
 //
 // int formula(int n1, int n2)
 // {
 //     if (n1 != n2) {
 //         if (n1 > n2)
 //             return n1 - n2;
 //         else
 //             return n1;
 //     } else {
 //         return n1 + (n1 * 2);
 //     }
 // }
 //

 template<typename N1, typename N2>
 struct formula 
     : mpl::eval_if<
           mpl::not_equal_to<N1, N2>,
           mpl::eval_if<
               mpl::greater<N1, N2>, 
               mpl::minus<N1, N2>, 
               N1
           >,
           mpl::plus<
               N1, 
               mpl::multiplies<
                   N1, 
                   mpl::int_<2> 
               >
           >
       >
 {};

 //////////////////////////////////////////////////////////////////////////////
 // Adriy Tylychko (telya at mail dot ru)
 // The solution above is correct but some "::type"'s don't need
 // to be removed to receive the same effect, so I think version:
	template< typename N1, typename N2 >
	struct formula
		: mpl::eval_if<
			mpl::not_equal_to<N1,N2>
			, typename mpl::eval_if<
				mpl::greater<N1,N2>
				, typename mpl::minus<N1,N2>
				, N1
			>::type
			, typename mpl::plus<
				N1
				, typename mpl::times<
					N1,
					mpl::int_<2>
				>
			>
		>::type
	{};
 // is "more correct" :)
 ///////////////////////////////////////////////////////////////////

 template<typename Nullary>
 struct make_class
 {
     template<typename>
     struct apply : Nullary {};
 };

 typedef make_class<mpl::false_> never;
 typedef make_class<mpl::true_> always;

 int main()
 {
     typedef mpl::int_<1> one;

     typedef next_if<one, never>::type still_one;
     BOOST_STATIC_ASSERT((still_one::type::value == 1));

     typedef next_if<one, always>::type two;
     BOOST_STATIC_ASSERT((two::type::value == 2));

 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Andriy Tylychko (telya at mail dot ru)
 // the solution above works because "adapted" predicates are used (ones that have nested "apply")
 // following example cannot be compiled, at least using VC8:
     BOOST_STATIC_ASSERT((next_if<mpl::int_<1>, mpl::equal_to<mpl::int_<1>, _> >::type::value == 2));
 // to fix, "::type" shoul be returned to "mpl::apply<Predicate, N>", in any case this instantiation
 // cannot be ommitted. 
 // So, final changes consist of: 
 //   a) change mpl::if_ to mpl::eval_if
 //   b) remove "::type" from "typename mpl::next<N>::type"
 ///////////////////////////////////////////////////////////////////////////////////////////////////

     BOOST_STATIC_ASSERT((formula<one, still_one>::type::value == 3));
     BOOST_STATIC_ASSERT((formula<one, two>::type::value == 1));
     BOOST_STATIC_ASSERT((formula<two, one>::type::value == 1));

     return 0;
 }

BOOST WIKI | RecentChanges | Preferences | Page List | Links List
Edit text of this page | View other revisions
Last edited July 22, 2006 5:20 am (diff)
Search:
Disclaimer: This site not officially maintained by Boost Developers