std::numeric_limits<T>::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++14)
(C++11)
(C++11)(until C++20)
(C++11)(deprecated in C++20)
(C++11)
Type trait constants
Metafunctions
(C++17)
Endian
(C++20)
Constant evaluation context
Supported operations
Relationships and property queries
(C++11)
(C++11)
Type modifications
(C++11)(C++11)(C++11)
Type transformations
(C++11)
(C++11)
(C++17)
(C++11)(until C++20)(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 are possible to (until C++11)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.

is_modulo is false for signed integer types, unless the implementation defines signed integer overflow to wrap.

(since C++11)

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
char8_t true
char16_t true
char32_t true
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.", it is a defect and has been corrected. 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. 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.

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

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 2422 C++11 is_modulo was required to true
for signed integer types on most machines
required to be false for signed integer types
unless signed integer overflow is defined to wrap

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)