enum class storage_type { fast, least };

template<intmax_t minimum, intmax_t maximum, typename overflow_policy, storage_type storage> class integer;

- overflow_policy_type
- The template parameter overflow_policy
- underlying_type
- The basic C++ integer type that actually holds the data. If storage_type is set to fast, this corresponds with the fast typedefs in cstdint. If storage_type is set to least, this corresponds with the least typedefs (smallest space used).

- integer() // default constructor
- Does not initialize its value, the same as saying
*int x;*. noexcept - constexpr integer(
*integer_type*other) - Sets the value of the new object to the value of the old object. If
*integer_type*is a*bounded::integer*, it forwards the overflow policy of other into the overflow policy of this object. The constructor is implicit if the range of*integer_type*fits entirely within the range of the*minimum*and*maximum*template parameters, as determined by querying*std::numeric_limits*. The constructor is explicit if there is overlap in the range of legal values or the overflow policy has the static member variable*overflow_is_error*set to false. Otherwise, the constructor does not participate in overload resolution. If the argument is an enum type, the same conditions apply to the underlying_type, except that the constructor is never implicit. Throws whatever exceptions are thrown by the overflow policy's member function*assignment*. - constexpr integer(
*integer_type*other, overflow_policy_type policy) - Same as above, but uses the specified overflow policy instead of the overflow policy of
*other*. - constexpr integer(
*integer_type*other, bounded::non_check_t) - Same as above, but never applies the overflow policy to the value. If the value is out of range, the behavior is undefined. noexcept
- constexpr integer(
*integer_type*other, overflow_policy_type policy, bounded::non_check_t) - Combination of the previous two constructors. noexcept

- auto operator=(
*integer_type*other) & -> integer & - Assigns the value of other to this object. Does not alter the value of this object's overflow_policy. Throws whatever exceptions are thrown by the overflow policy's member function
*assignment*. - auto operator=(
*integer_type*other) volatile & -> integer volatile & - Same as above.
- auto unchecked_assignment(
*integer_type*other) & -> integer & - Assigns the value of other to this object. Does not alter or apply the overflow policy. noexcept.
- auto unchecked_assignment(
*integer_type*other) volatile & -> integer volatile & - Same as above.

- constexpr auto value() const -> underlying_type const &
- Returns the stored value. noexcept
- constexpr auto value() const volatile -> underlying_type const volatile &
- Returns the stored value. noexcept
- constexpr explicit operator
*integer_type*() const - Converts to whatever integer type was requested. noexcept.
- constexpr auto overflow_policy() const -> overflow_policy_type const &
- Returns the overflow policy. noexcept.
- constexpr auto overflow_policy() const volatile -> overflow_policy_type const volatile &
- Returns the overflow policy. noexcept.
- constexpr auto overflow_policy() -> overflow_policy_type &
- Returns the overflow policy. noexcept.
- constexpr auto overflow_policy() volatile -> overflow_policy_type volatile &
- Returns the overflow policy. noexcept.

An overflow policy has the following requirements:

- Type overflow_policy_tag. The contents of this type are irrelevant and can be type void, it simply has to be present.
- static constexpr bool is_modulo
- static constexpr bool overflow_is_error
- auto assignment(
*source_integer_type*source,*minimum_integer_type*minimum,*maximum_integer_type*maximum) ->*integer_type*. The return value of this function should always be between mimimum and maximum. - Constructible from any other policy (as determined by the presence of the member type overflow_policy_tag)

Additionally, if the overflow policy is DefaultConstructible, so will the bounded::integer that uses this policy.

The null_policy is the most basic policy of all. Its solution to out-of-bounds values is to declare them to be undefined behavior. If the values are used in a constexpr context, this policy does perform out-of-bounds checking, but it does not perform a run-time check.

- static constexpr bool is_modulo = false;
- static constexpr bool overflow_is_error = true;

If an out-of-bounds value is passed to assignment, it throws an exception of type std::range_error.

- static constexpr bool is_modulo = false;
- static constexpr bool overflow_is_error = true;

If an a value less than minimum is passed to assignment, it returns minimum. If a value greater than maximum is passed to assignment, it returns maximum.

- static constexpr bool is_modulo = false;
- static constexpr bool overflow_is_error = false;

There are three policy adapters defined as well: dynamic_policy, dynamic_min_policy, and dynamic_max_policy. dynamic_min_policy has a value that can be set at run-time that can further restrict the minimum bound beyond that of the static bound. dynamic_max_policy has a value that can be set at run-time that can further restrict the maximum bound beyond that of the static bound. dynamic_policy has both. All dynamic policies have member functions min and max that allow the user to retrieve the value (or assign to it, where appropriate). All of them accept the following template parameters:

template<intmax_t static_minimum, intmax_t static_maximum, typename overflow_policy, storage_type storage = storage_type::fast>

These parameters are passed directly to the bounded::integer type that will hold the run-time bound. If the overflow_policy template parameter is stateful, each dynamic policy has its own copy of that state that is separate from the state of the dynamic bounds.

There is a *template<typename policy> basic_policy;* defined to reduce boilerplate for most simple policies. If the policy passed in as a template parameter defines the member variables *is_modulo*, *overflow_is_error* and *assignment*, basic_policy provides all other requirements, including the ability to constrct from any other policy. basic_policy can only be used with stateless policies.

Similar to std::common_type, the bounded library has a metafunction common_policy. This can be specialized as long as least one of the types in the specialization is a user-defined policy. It accepts any number of types greater than zero. There is also an alias template, *common_policy_t*, to mirror std::common_type_t.

For three or more policies passed in, the metafunction is recursively applied, two policies at a time.

*common_policy* has a nested type

In other words, the null_policy 'loses' to any other policy, otherwise, it is a compile-time error to attempt to get the common_policy of mixed policies.

namespace bounded { template<intmax_t minimum, intmax_t maximum> using checked_integer = integer<minimum, maximum, throw_policy>; template<intmax_t minimum, intmax_t maximum> using clamped_integer = integer<minimum, maximum, clamp_policy>; template<intmax_t minimum, intmax_t maximum, typename base_overflow_policy = throw_policy> using dynamic_integer = integer<minimum, maximum, dynamic_policy<minimum, maximum, base_overflow_policy>>; template<intmax_t minimum, intmax_t maximum, typename base_overflow_policy = throw_policy> using dynamic_min_integer = integer<minimum, maximum, dynamic_min_policy<minimum, maximum, base_overflow_policy>>; template<intmax_t minimum, intmax_t maximum, typename base_overflow_policy = throw_policy> using dynamic_max_integer = integer<minimum, maximum, dynamic_max_policy<minimum, maximum, base_overflow_policy>>; } // namespace bounded

All basic arithmetic operators return by value. bounded::integer supports the following arithmetic operators:

- unary plus (+a)
- The type of the output is the same as
*a*. - unary minus (-a)
- The type of the output has the same overflow policy and storage_type as
*a*, but the bounds can now hold the negation of the original values. For instance, if*a*was between 1 and 10, -a is between -10 and -1. - addition (a + b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any sum of
*a*and*b*. - subtraction (a - b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any difference of
*a*and*b*. - multiplication (a * b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any product of
*a*and*b*. - division (a / b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any quotient of
*a*and*b*. This fails to compile with a static_assert if the min or max of*b*is 0. - modulo (a % b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any remainder of
*a*and*b*. This follows the same rules as built-in types with regards to the sign of the result. The net effect is that the sign of the result is the same as the sign of*a*. This fails to compile with a static_assert if the min or max of*b*is 0. - left shift (a << b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any shifted value of
*a*by*b*. This fails to compile with a static_assert if either*a*or*b*can be negative. - right shift (a >> b)
- This is only defined for bounded::integer with the same storage_type. The resulting type is able to store any shifted value of
*a*by*b*. This fails to compile with a static_assert if either*a*or*b*can be negative.

All of the above binary operators have an equivalent compound assignment operator (+=, -=, *=, /=, %=, <<=, >>=). These behave the same as first calling the above operator, then calling the assignment operator on the left-hand-side argument.

bounded::integer supports all of the comparison / relational operators (==, !=, <, >, <=, >=). Any bounded::integer can be compared with any other bounded::integer or any built-in type. Doing so never invokes undefined behavior, nor are there any surprising changes in value. A bounded::integer with a value of -1 will always compare less than any value of std::uintmax_t, for instance.

The bounded namespace contains all overloads of to_string that exist for std::to_string (by way of *using std::to_string*). It also provides overloads for bounded::integer types. The result of calling this function is the same as calling std::to_string on the underlying_type, except that if the underlying_type is a character type, it is first promoted to int. The underlying type can be a character type on many systems where std::uint8_t is just a typedef for unsigned char, for example.

bounded::integer overloads are provided for the insertion (<<) and extraction (>>) operators for a left-hand-side argument of std::basic_ostream. This inputs / outputs the value formatted as an integer. Very large integer values input can invoke undefined behavior, as operator>> first pulls in the value as std::intmax_t and then constructs a bounded::integer from that. This is a temporary limitation of the current implementation.

bounded::integer provides a specialization of std::numeric_limits. It provides all of the required values / functions.

- static constexpr bool is_specialized
- true
- static constexpr bool is_signed
- true if the minimum value is less than 0, otherwise false.
- static constexpr bool is_integer
- true
- static constexpr bool is_exact
- true
- static constexpr bool has_infinity
- false
- static constexpr bool has_quiet_NaN
- false
- static constexpr std::float_denorm_style has_denorm
- std::denorm_absent
- static constexpr bool has_denorm_loss
- false
- static constexpr std::float_round_style round_style
- std::round_toward_zero
- static constexpr bool is_iec559
- false
- static constexpr bool is_bounded
- true
- static constexpr bool is_modulo
- The same as the overflow policy's is_modulo member
- static constexpr int radix
- 2
- static constexpr int digits
- The number of digits in base 2.
- static constexpr int digits10
- The number of digits in base 10.
- static constexpr int max_digits10
- 0
- static constexpr int min_exponent
- 0. Not meaningful because this is an integer type.
- static constexpr int min_exponent10
- 0. Not meaningful because this is an integer type.
- static constexpr int max_exponent
- 0. Not meaningful because this is an integer type.
- static constexpr int max_exponent10
- 0. Not meaningful because this is an integer type.
- static constexpr bool traps
- true if 0 is in the range of possible values and the underlying type traps.
- static constexpr bool tinyness_before
- false. Not meaningful because this is an integer type.
- static constexpr bounded::integer<minimum, minimum, overflow_policy, storage> min()
- Returns the minimum value. noexcept. Note that the return type is not the same as the type passed in. This is because it is statically known what the bounds are, and they can be much tighter than returning the exact bounded::integer type.
- static constexpr bounded::integer<minimum, minimum, overflow_policy, storage> lowest()
- Returns the minimum value. noexcept. Note that the return type is not the same as the type passed in. This is because it is statically known what the bounds are, and they can be much tighter than returning the exact bounded::integer type.
- static constexpr bounded::integer<maximum, maximum, overflow_policy, storage> max()
- Returns the maximum value. noexcept. Note that the return type is not the same as the type passed in. This is because it is statically known what the bounds are, and they can be much tighter than returning the exact bounded::integer type.
- static constexpr
*implementation defined type*epsilon() - Returns some undefined value. Not meaningful because this is an integer type.
- static constexpr
*implementation defined type*round_error() - Returns some undefined value. Not meaningful because this is an integer type.
- static constexpr
*implementation defined type*infinity() - Returns some undefined value. Not meaningful because this is an integer type.
- static constexpr
*implementation defined type*quiet_NaN() - Returns some undefined value. Not meaningful because this is an integer type.
- static constexpr
*implementation defined type*signalling_NaN() - Returns some undefined value. Not meaningful because this is an integer type.
- static constexpr
*implementation defined type*denorm_min() - Returns some undefined value. Not meaningful because this is an integer type.

bounded::min accepts an arbitrary number of arguments and returns the least value as determined by operator<. When comparing integer types, if std::numeric_limits reports that the range of one is entirely less than the range of the other (for instance, bounded::integer<0, 5> is definitely less than bounded::integer<6, 10>), then the comparison function is not invoked. For bounded::integer arguments, the range of the result is the minimum of all the minimums and the minimum of all the maximums.

bounded::max is the same as bounded::min, except that it uses operator>.

There is a more general function, bounded::extreme. The first argument to this function is a comparison function that returns true if the first value is more extreme than the second. The result of the function is the most extreme value as determined by this comparison function. The type of the result by default uses std::common_type, but that can be changed by providing a specialization of template<typename Compare, typename T1, typename T2> class extreme_type in the bounded namespace that provides a member type named type. T1 and T2 will always be decayed (cv-qualifiers and references stripped).

bounded::abs accepts any bounded::integer and returns a new bounded::integer that is guaranteed to be non-negative. The result type has the same overflow_policy type and storage as the argument. noexcept.

increase_min accepts an integer as a template argument and a bounded::integer as a function argument. The return type is a bounded::integer that has a new minimum that is the greater of its original minimum and the specified minimum. The function also accepts more arguments, which will be passed to the constructor of the new bounded::integer type.

decrease_max is the same as the above, except the template argument can lower the maximum rather than raise the minimum.

template< typename T, typename overflow_policy =see below, storage_type storage = storage_type::fast > using equivalent_type = integer< detail::basic_numeric_limits<T>::min(), detail::basic_numeric_limits<T>::max(), overflow_policy, storage >;

This alias template allows the user to specify a type and get its equivalent bounded version. For instance, bounded::equivalent_type<std::int8_t> is the same as bounded::integer<-128, 127, bounded::null_policy> on most systems. The defaulted overflow_policy parameter is bounded::null_policy for signed built-in integer types and the same as T::overflow_policy_type for bounded::integer types. Currently unsigned built-in types default to bounded::null_policy, but this is a temporary defect caused by not having a bounded::modulo_policy.

template<typename overflow_policy =see below, storage_type storage = storage_type::fast, typename T =unspecified> constexpr auto make(T const value) noexcept -> equivalent_type<T, overflow_policy, storage>;

It is intended the the user specifies 0, 1, or 2 template arguments. A call like make(value) will return an instance of the type specified by bounded::equivalent_type<decltype(value)>. However, the user can explicitly specify the overflow_policy and the storage to be used by passing them as the first and second template arguments, respectively.

template<intmax_t value, typename overflow_policy = null_policy, storage_type storage = storage_type::fast> constexpr auto make() noexcept -> integer<value, value, overflow_policy, storage> { return {value, non_check}; }

This overload is used to create a bounded::integer that has a known compile-time value. The purpose is to reduce the duplication of the value as in a call to bounded::integer<5, 5>(5) . Instead, you would simply use bounded::make<5>() .

The namespace bounded::literal contains a user defined integer literal _bi. This creates a bounded::integer with a min and max equal to the value. For example, 10_bi is the same as bounded::integer<10, 10, bounded::null_policy>(10) .

bounded::next is the same as std::next, except the default value is 1_bi instead of 1 (type of bounded::integer<1, 1> instead of int). bounded::prev is the same as std::prev, except its default value is also 1_bi instead of 1.

For a given type T, bounded::is_bounded_integer derives from std::true_type if the type is a bounded::integer, otherwise it derives from std::false_type.

`BOUNDED_CONDITIONAL` is a macro that accepts three arguments. The first argument is evaluated in `operator?:` as the first (boolean) argument. The result of the macro is the second argument if the condition is true, otherwise it is the third argument. The type of the result is the common type (as determined by std::common_type) and value category of the second and third arguments.

This exists as a workaround for a limitation of `operator?:`. The built-in operator attempts to convert each argument to the type of the other. This means that a statement like `true ? 1_bi : 2_bi` does not compile, as neither argument can be converted to the other. `BOUNDED_CONDITIONAL(true, 1_bi, 2_bi)`, however, returns the value 1, and the type is bounded::integer<1, 2>.

This library provides specializations for the class template std::common_type. The common_type of two bounded::integer types is another bounded::integer type. The minimum is the lesser of the two minimums, the maximum is the greater of the two maximums, and the policy is the result of common_policy. This specialization only exists when both arguments have the same storage_type.

The bounded library provides functions that are nearly identical to std::count and std::count_if. The difference is the type returned. bounded::count and bounded::count_if return the type bounded::integer<0, std::numeric_limits<iterator_difference_type>::max()>.

The header bounded_integer/integer_range.hpp defines two function overloads of bounded::integer_range: bounded::integer_range(begin, end) and bounded::integer_range(size), where begin, end, and size are all integers. bounded::integer_range(size) is equivalent to bounded::integer_range(0, size). The return type of this function is such that it can be used in a range-based for loop.

The given range contains all the values from begin to end, including begin but excluding end. For example, the code for (auto x : bounded::integer_range(5_bi) will result in x having the values 0, 1, 2, 3, and 4. The type of x is bounded::integer<0, 4>. The numbers are generated on demand, so it has O(1) space complexity in the size of the range.