82 template <
bool B,
class T =
void>
113 template <
typename T>
115 T summand_1, T summand_2, T& result)
117 if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
118 ((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
121 result = summand_1 + summand_2;
145 template <
typename T>
146 typename enable_if<is_signed<T>::VALUE &&
sizeof(T) <
sizeof(
int),
bool>::type fallback_add_overflow(
147 T summand_1, T summand_2, T& result)
149 const int res = summand_1 + summand_2;
150 if ((res > std::numeric_limits<T>::max()) || (res < std::numeric_limits<T>::min())) {
153 result =
static_cast<T
>(res);
174 template <
typename T>
175 typename enable_if<!is_signed<T>::VALUE,
bool>::type fallback_add_overflow(T summand_1, T summand_2, T& result)
177 result = summand_1 + summand_2;
178 return result < summand_1;
194 template <
typename T>
195 bool builtin_add_overflow(T summand_1, T summand_2, T& result)
197 return fallback_add_overflow(summand_1, summand_2, result);
200#if defined(__GNUC__) || defined(__clang__)
201#if __GNUC__ >= 5 || __clang_major__ >= 3
213#define SPECIALIZE_builtin_add_overflow(type, builtin_name) \
217 inline bool builtin_add_overflow<type>(type summand_1, type summand_2, type & result) \
219 return builtin_name(summand_1, summand_2, &result); \
222 SPECIALIZE_builtin_add_overflow(
int, __builtin_sadd_overflow);
223 SPECIALIZE_builtin_add_overflow(
long, __builtin_saddl_overflow);
224 SPECIALIZE_builtin_add_overflow(
long long, __builtin_saddll_overflow);
226 SPECIALIZE_builtin_add_overflow(
unsigned int, __builtin_uadd_overflow);
227 SPECIALIZE_builtin_add_overflow(
unsigned long, __builtin_uaddl_overflow);
228 SPECIALIZE_builtin_add_overflow(
unsigned long long, __builtin_uaddll_overflow);
230#undef SPECIALIZE_builtin_add_overflow
233#elif defined(_MSC_VER)
250#define SPECIALIZE_builtin_add_overflow_WIN(type, builtin_name) \
252 inline bool builtin_add_overflow(type summand_1, type summand_2, type& result) \
254 return builtin_name(summand_1, summand_2, &result) != S_OK; \
257 SPECIALIZE_builtin_add_overflow_WIN(
unsigned int, UIntAdd);
258 SPECIALIZE_builtin_add_overflow_WIN(
unsigned long, ULongAdd);
259 SPECIALIZE_builtin_add_overflow_WIN(
unsigned long long, ULongLongAdd);
261#undef SPECIALIZE_builtin_add_overflow_WIN
287 template <
typename T>
288 T
add(T summand_1, T summand_2)
291 if (Internal::builtin_add_overflow(summand_1, summand_2, res)) {
292 throw std::overflow_error(
"Overflow in addition");
319 template <
typename T>
322 if (num == std::numeric_limits<T>::min()) {
323 return std::numeric_limits<T>::max();
325 return num < 0 ? -num : num;
Arithmetic operations with overflow checks.
Definition: safe_op.hpp:35
T add(T summand_1, T summand_2)
Safe addition, throws an exception on overflow.
Definition: safe_op.hpp:288
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:320
Helper struct for SFINAE, from C++11.
Definition: safe_op.hpp:84
Helper struct to determine whether a type is signed or unsigned.
Definition: safe_op.hpp:69