std::numeric_limits::is_modulo

From cppreference.com
 
 
 
Type support
Basic types
Fundamental types
Fixed width integer types (C++11)
Numeric limits
C numeric limits interface
Runtime type information
Type traits
Type categories
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Type properties
(C++11)
(C++11)
(C++11)
(C++14)
(C++11)
(C++11)(deprecated in C++17)
(C++11)
Type trait constants
Metafunctions
(C++17)
Supported operations
Relationships and property queries
(C++11)
(C++11)
(C++11)
(C++11)
Type modifications
(C++11)(C++11)(C++11)
Type transformations
(C++11)
(C++11)
(C++17)
(C++11)(deprecated in C++17)(C++17)
 
 
static const bool is_modulo;
(until C++11)
static constexpr bool is_modulo;
(since C++11)

The value of std::numeric_limits<T>::is_modulo is true for all arithmetic types T that handle overflows with modulo arithmetic, that is, if the result of addition, subtraction, multiplication, or division of this type would fall outside the range [min(), max()], the value returned by such operation differs from the expected value by a multiple of max()-min()+1.

Standard specializations

T value of std::numeric_limits<T>::is_modulo
/* non-specialized */ false
bool false
char implementation-defined
signed char implementation-defined
unsigned char true
wchar_t implementation-defined
char16_t implementation-defined
char32_t implementation-defined
short implementation-defined
unsigned short true
int implementation-defined
unsigned int true
long implementation-defined
unsigned long true
long long implementation-defined
unsigned long long true
float false
double false
long double false

Notes

Although the C++11 standard still says "On most machines, this is true for signed integers.", the exact wording changed from C++03 to C++11 in such a way that the true value is no longer compatible with undefined behavior on signed integer overflow (it changed from "possible" to a strict requirement). Because of that, the implementations that rely on signed overflow being undefined (for optimization opportunities) now set is_modulo to false for signed integers. See for example GCC PR 22200.

The standard wording is expected to change to "is_modulo is false for signed integer types unless an implementation defines signed integer overflow to wrap" per LWG issue 2422.

Example

Demonstrates the behavior of modulo types

#include <iostream>
#include <type_traits>
#include <limits>
 
template<class T>
typename std::enable_if<std::numeric_limits<T>::is_modulo>::type
    check_overflow()
{
    std::cout << "\nmax value is " << std::numeric_limits<T>::max() << '\n'
              << "min value is " << std::numeric_limits<T>::min() << '\n'
              << "max value + 1 is " << std::numeric_limits<T>::max()+1 << '\n';
}
 
int main()
{
    check_overflow<int>();
    check_overflow<unsigned long>();
    // check_overflow<float>(); // compile-time error, not a modulo type
}

Possible output:

max value is 2147483647
min value is -2147483648
max value + 1 is -2147483648
 
max value is 18446744073709551615
min value is 0
max value + 1 is 0

See also

[static]
identifies integer types
(public static member constant)
[static]
identifies the IEC 559/IEEE 754 floating-point types
(public static member constant)
[static]
identifies exact types
(public static member constant)