Search code examples
c++boostc++11template-meta-programmingboost-mpl

`mpl::plus< mpl::int_<1>, mpl::int_<2> >::type` not the same type as `mpl::int_<3>`?


The code below reproduces a behavior I really don't understand of the boost MPL library:

#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/plus.hpp>

using namespace boost;

int main() {
  typedef mpl::int_<1> one;
  typedef mpl::int_<2> two;
  typedef mpl::int_<3> three;
  // The following line breaks compilation...
  // static_assert( is_same< mpl::plus<one,two>::type, three >::type::value, "Not the same type");
  // ...while this works
  static_assert( mpl::plus<one,two>::type::value == three::value , "Not the same value");
  return 0;
}

The question I have is: why mpl::plus<one,two>::type is not the same type as three?

I ran into this issue while trying to solve the exercises at the end of chapter 3 of C++ Template Meta-Programming. I already tried to peek at <boost/mpl/plus.hpp> and the includes therein, but the code was too complicated for me to be understandable.


Solution

  • The return type of plus is only guaranteed to be an integral constant. You have no guarantee over it's exact type, hence your assert is allowed to fail.

    The exact types are this:

    mpl::plus<one,two>::type == mpl_::integral_c<int, 3>
    three == foo<mpl_::int_<3> >
    

    This is unintuitive. One problem is that plus<int_, int_> theoretically can return a integral_c where the first argument has a larger capacity then int_ in case of overflow.

    For debugging a type printer can be useful:

    template<typename> print; // undefined instantiation leads to error with name
    print<three> x; // nice error message