std::numeri...::is_modulo(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– std::numeric_limits::is_modulo(3) πŸ’–

okay bestie, welcome to the C++ Standard Libary manual. today’s main character is std::numeric_limits::is_modulo, and ngl it’s giving β€œtiny trait, big overflow opinions.” no cap. πŸ’…

🌸 NAME 🌸

std::numeric_limits::is_modulo β€” std::numeric_limits::is_modulo

✨ Synopsis ✨

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. wrap-around math, fr fr. πŸŒ€

is_modulo is false for signed integer types, unless the implementation defines signed integer overflow to wrap. that β€œunless” is doing a lot, bestie β€” lowkey obsessed with how much work one clause can do. πŸ‘€

🌈 Standard specializations 🌈

here’s the full vibe check: T on the left, value of std::numeric_limits<T>::is_modulo on the right:

  • /* non-specialized */ β€” false
  • bool β€” false
  • char β€” implementation-defined
  • signed char β€” implementation-defined
  • unsigned char β€” true
  • wchar_t β€” implementation-defined
  • char8_t (since C++20) β€” true
  • char16_t (since C++11) β€” true
  • char32_t (since C++11) β€” true
  • short β€” implementation-defined
  • unsigned short β€” true
  • int β€” implementation-defined
  • unsigned int β€” true
  • long β€” implementation-defined
  • unsigned long β€” true
  • long long (C++11) β€” implementation-defined
  • unsigned long long (C++11) β€” true
  • float β€” false
  • double β€” false
  • long double β€” false

πŸ“ Notes πŸ“

The standard said "On most machines, this is true for signed integers." before the resolution of LWG issue 2422. See GCC PR 22200 for a related discussion.

that’s the whole note, bestie β€” historical lore and a GCC PR reference, iconic behavior. 🫢

πŸ’» Example πŸ’»

Demonstrates the behavior of modulo types:

There’s a // Run this code marker in the original, so let’s run this code:

#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 << "max 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>();
    std::cout << '\n';
    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:

  • LWG 612 β€” applied to C++98. Behavior as published: the definition of "handle overflows with modulo arithmetic" was poor^[1]. Correct behavior: provided a better definition.
  • LWG 2422 β€” applied to C++98. Behavior as published: is_modulo was required to be true for signed integer types on most machines. Correct behavior: required to be false for signed integer types unless signed integer overflow is defined to wrap.
  1. ↑ The definition is "adding two positive numbers can have a result that wraps around to a third number that is less". It has the following problems:
    • It does not define the wrapped value.
    • It does not state whether result is repeatable.
    • It does not require that doing addition, subtraction and other operations on all values have defined behavior.

πŸ”— See also πŸ”—

  • is_integer β€” identifies integer types; [static] (public static member constant).
  • is_iec559 β€” identifies the IEC 559/IEEE 754 floating-point types; [static] (public static member constant).
  • is_exact β€” identifies exact types; [static] (public static member constant).

πŸ’– that’s the whole page, bestie β€” source: http://cppreference.com, version/date: 2024.06.10, page: std::numeric_limits::is_modulo(3). byeee! πŸ’–

πŸ“¦ where this page comes from