89 template <
bool B,
class T =
void>
120 template <
typename T>
122 T summand_1, T summand_2, T& result)
124 if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
125 ((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
128 result = summand_1 + summand_2;
152 template <
typename T>
153 typename enable_if<is_signed<T>::VALUE &&
sizeof(T) <
sizeof(
int),
bool>::type fallback_add_overflow(
154 T summand_1, T summand_2, T& result)
156 const int res = summand_1 + summand_2;
157 if ((res > std::numeric_limits<T>::max()) || (res < std::numeric_limits<T>::min())) {
160 result =
static_cast<T
>(res);
181 template <
typename T>
182 typename enable_if<!is_signed<T>::VALUE,
bool>::type fallback_add_overflow(T summand_1, T summand_2, T& result)
184 result = summand_1 + summand_2;
185 return result < summand_1;
201 template <
typename T>
202 bool builtin_add_overflow(T summand_1, T summand_2, T& result)
204 return fallback_add_overflow(summand_1, summand_2, result);
207 #if defined(__GNUC__) || defined(__clang__) 208 #if __GNUC__ >= 5 || __clang_major__ >= 3 220 #define SPECIALIZE_builtin_add_overflow(type, builtin_name) \ 224 inline bool builtin_add_overflow<type>(type summand_1, type summand_2, type & result) \ 226 return builtin_name(summand_1, summand_2, &result); \ 229 SPECIALIZE_builtin_add_overflow(
int, __builtin_sadd_overflow);
230 SPECIALIZE_builtin_add_overflow(
long, __builtin_saddl_overflow);
231 SPECIALIZE_builtin_add_overflow(
long long, __builtin_saddll_overflow);
233 SPECIALIZE_builtin_add_overflow(
unsigned int, __builtin_uadd_overflow);
234 SPECIALIZE_builtin_add_overflow(
unsigned long, __builtin_uaddl_overflow);
235 SPECIALIZE_builtin_add_overflow(
unsigned long long, __builtin_uaddll_overflow);
237 #undef SPECIALIZE_builtin_add_overflow 238 #endif // __GNUC__ >= 5 || __clang_major >= 3 240 #elif defined(_MSC_VER) 257 #define SPECIALIZE_builtin_add_overflow_WIN(type, builtin_name) \ 259 inline bool builtin_add_overflow(type summand_1, type summand_2, type& result) \ 261 return builtin_name(summand_1, summand_2, &result) != S_OK; \ 264 SPECIALIZE_builtin_add_overflow_WIN(
unsigned int, UIntAdd);
265 SPECIALIZE_builtin_add_overflow_WIN(
unsigned long, ULongAdd);
266 SPECIALIZE_builtin_add_overflow_WIN(
unsigned long long, ULongLongAdd);
268 #undef SPECIALIZE_builtin_add_overflow_WIN 270 #endif // _MSC_VER >= 1400 271 #endif // defined(_MSC_VER) 294 template <
typename T>
295 T
add(T summand_1, T summand_2)
298 if (Internal::builtin_add_overflow(summand_1, summand_2, res)) {
299 throw std::overflow_error(
"Overflow in addition");
326 template <
typename T>
329 if (num == std::numeric_limits<T>::min()) {
330 return std::numeric_limits<T>::max();
332 return num < 0 ? -num : num;
337 #endif // SAFE_OP_HPP_ Arithmetic operations with overflow checks.
Definition: safe_op.hpp:41
Helper struct to determine whether a type is signed or unsigned.
Definition: safe_op.hpp:75
Helper struct for SFINAE, from C++11.
Definition: safe_op.hpp:90
T add(T summand_1, T summand_2)
Safe addition, throws an exception on overflow.
Definition: safe_op.hpp:295
Internal::enable_if< Internal::is_signed< T >::VALUE, T >::type abs(T num)
Calculates the absolute value of a number without producing negative values.
Definition: safe_op.hpp:327