Здравствуйте, Marty, Вы писали:
M> Понадобилось тут немного арифметики, решил сам наваять,
Понадобилось? Зачем? Почему не подошло готовое?
M> дело вообщем-то нехитрое ;)
Ну и раз нехитрое, то что же код деления не привёл тогда? )
M> Использовал этуАвтор: Lorenzo_LAMAS
Дата: 12.04.12
тему.
Ну, видимо невнимательно прочитал ту тему. Вот например:
M>// returns true if carry detected
M>inline bool signed_addition( INT32 a, INT32 b, INT32 *c = 0 )
M>{
M> INT32 r = a + b; if (c) *c = r; return !(b >= 0 == r >= a);
M>}
Переполнение для знаковых чисел — неопределённое поведение. Твоя проверка
!(b >= 0 == r >= a) бессмысленна и неверна.
Компилятор, например, аналогично считает:
http://goo.gl/2Gcbx4 — в результирующем кода функция всегда возвращает false. Ну и это очевидно почему так: если после сложения результат не вызвал переполнения, то возвращаем false. Если вызвал, то произошло UB и всё равно что функция будет возвращать, поэтому также возвращаем false, так как это не требует дополнительного кода. И оказывается, что от проверки ничего не зависит, и её можно смело игнорировать.
M>template<> bool integer_addition<INT16> (INT16 a, INT16 b, INT16 *c) { return signed_addition( a, b, c ); }
M>template<> bool integer_addition<INT16> (INT16 a, INT16 b, INT16 &c) { return signed_addition( a, b, c ); }
M>template<> bool integer_addition<INT32> (INT32 a, INT32 b, INT32 *c) { return signed_addition( a, b, c ); }
M>template<> bool integer_addition<INT32> (INT32 a, INT32 b, INT32 &c) { return signed_addition( a, b, c ); }
M>template<> bool integer_addition<INT64> (INT64 a, INT64 b, INT64 *c) { return signed_addition( a, b, c ); }
M>template<> bool integer_addition<INT64> (INT64 a, INT64 b, INT64 &c) { return signed_addition( a, b, c ); }
Кошмар. Шаблоны нужны чтобы избавиться от копипасты, а не чтобы сделать её в несколько раз больше. Ну вот зачем тебе тут специализация? Зачем вообще вызвать нешаблонные unsigned_addition из шаблонных integer_addition?
Я ещё понимаю, если бы ты разделял код для знаковых и беззнаковых типов (но даже для этого специализация не нужна), но вот это дублирование для всех размеров совсем ужасно.
M>template<typename IntT>
M>IntT integer_abs( IntT i ) { return (i<0) ? -i : /*return*/ i; }
Эта функция у тебя иногда возвращает отрицательный результат вследствие переполнения на минимальном целом.