И размышляя таким образом о физической природе чисел я дошел до стандартной библиотеки...
C++ конечно, язык со строгой типизацией - никуда не денешься.
Сравнение знакового и беззнакового числа нелогично только с точки зрения ограниченности платформы. Мы знаем, что компилятор пытается привести числа к одному типу с чем испытывает многочисленные проблемы.
Хотя с точки зрения математики int(-10) определенно меньше чем uint(10). А int(-2000000000) определенно меньше uint(3000000000). Почему же нам запрещают их сравнивать?
То же самое касается min/max, которые вообще требуют строго одинаковых типов - негибко.
Гибкость с типами позволяет, кроме того, гораздо шире трактовать понятие целое число.
И это даже можно реализовать...
Только почему-то наткнулся на странную фигню - компилятор говорит что нельзя реализовать шаблонный operator < вне класса... Ну да ладно, продемонстрирую идею на примере min Для начала напишем тестик:
BOOST_AUTO_TEST_CASE(minimal)Первая строка - вызывает стандартный min, Но последующие две строки под него никак не подходят.
{
BOOST_REQUIRE_EQUAL(min(-10, 10), -10);
BOOST_REQUIRE_EQUAL(min(-2000000000, 3000000000), -2000000000);
BOOST_REQUIRE_EQUAL(min(3000000000, -2000000000), -2000000000);
}
И тут вступает наша реализация:
template<typename A, typename B> struct min_type_selector { typedef typename mpl::if_c<is_signed<A>::value, typename mpl::if_c<is_signed<B>::value, typename mpl::if_c<(sizeof(A) > sizeof(B)), A, B>::type, A>::type, typename mpl::if_c<is_signed<B>::value, B, typename mpl::if_c<(sizeof(A) > sizeof(B)), A, B>::type>::type >::type type; // Переполнение результата может вызвать только беззнаковое значение, // По размеру не меньше резулььтата enum { b_can_overload = ((sizeof(B) >= sizeof(type) && is_unsigned<B>::value)) }; enum { a_can_overload = ((sizeof(A) >= sizeof(type) && is_unsigned<A>::value)) }; static type highest() { return numeric::bounds<type>::highest(); } }; template<typename A, typename B> typename min_type_selector<A, B>::type min(const A &a, const B &b) { typedef min_type_selector<A, B> TS; if (TS::b_can_overload && b > numeric_cast<B>(TS::highest())) return numeric_cast<typename TS::type>(a); if (TS::a_can_overload && a > numeric_cast<A>(TS::highest())) return numeric_cast<typename TS::type>(b); return min(numeric_cast<typename TS::type>(a), numeric_cast<typename TS::type>(b)); }Вот...
Кому нужно сравнивать такие большие числа - не очень то понятно, но может быть это пригодиться для того, чтобы постоянно не приводить два сравниваемых числа к одному типу?
А может и проще можно написать?
0 коммент.:
Отправить комментарий