The following code illustrates my problem
#include <type_traits> #include <limits> #include <cstdint> #include <boost/mpl/if.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> ///////////////////////////////////////////////////////////////// // safe_signed_range template < std::intmax_t MIN, std::intmax_t MAX > struct safe_signed_range { }; ///////////////////////////////////////////////////////////////// // safe_unsigned_range template < std::uintmax_t MIN, std::uintmax_t MAX > struct safe_unsigned_range { }; template<class T, class U> using calculate_max_t = typename boost::mpl::if_c< std::numeric_limits<T>::is_signed || std::numeric_limits<U>::is_signed, std::intmax_t, std::uintmax_t >::type; template<typename T, typename U> struct test { typedef calculate_max_t<T, U> max_t; static_assert(std::is_same<max_t, std::intmax_t>::value, "unexpected value for max_t"); static_assert(std::is_signed<max_t>::value, "check parameter"); /* typedef typename boost::mpl::if_c< std::is_signed<max_t>::value, safe_signed_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()>, safe_unsigned_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()> >::type type; */ typedef typename boost::mpl::eval_if_c< std::is_signed<max_t>::value, boost::mpl::identity<safe_signed_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()> >, // error shows up here boost::mpl::identity<safe_unsigned_range<std::numeric_limits<max_t>::min(), std::numeric_limits<max_t>::max()> > >::type type; }; test<int, int> t1; //test<int, unsigned> t2; //test<unsigned, int> t3; //test<unsigned, unsigned> t4; int main(){ return 0; }
an error appears with the Clang compiler as
/Users/robertramey/WorkingProjects/safe_numerics/test/test_z.cpp:116:50: Non-type template argument evaluates to -9223372036854775808, which cannot be narrowed to type 'std::uintmax_t' (aka 'unsigned long')
It seems that Boost Mpl is not choosing the right type. At first I suspected (and actually still suspect) that all the arguments in if are expanding, so I changed the use of eval_if, but still I have a problem. I turned on static_assert to check the parameters and can compromise it with the simplest tests - although it does not work in all combinations. If anyone can explain my mistake, I would be grateful.
source share