# CPPTM Answers - Exercise 4-3

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

Difference (from prior major revision) (author diff)

 ////////////////////////////////////////////////////////////////////////////// // 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 , typename mpl::eval_if< mpl::greater , typename mpl::minus , 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