Poniższy kod ilustruje mój problemC++ Template METAPROGRAMOWANIE kwestią wyboru typu
#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;
}
błąd pokazuje się z brzękiem kompilator jako
/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')
To wygląda jak Boost, MPL ISN wybierz właściwy typ. Najpierw podejrzewałem (i tak naprawdę wciąż podejrzewam), że wszystkie argumenty dotyczące tego, czy są rozszerzane, zmieniłem więc na eval_if, ale nadal mam problem. Zawarłem static_assert, aby sprawdzić parametry i sprawić, by zakończył się niepowodzeniem z najprostszym testem - choć nie przy wszystkich kombinacjach. Jeśli ktokolwiek może mi wyjaśnić mój błąd, byłbym wdzięczny.
OK - zadziałało - dobra robota i wielkie dzięki. Oczywiście była to moja motywacja do korzystania z mpl: tożsamość, która moim zdaniem powinna zrobić to samo. Zajrzę w to. Dzięki jeszcze raz. –