Current standard provides signed and unsigned int8_t, int16_t, int32_t, int64_t. It is usually enough for every day tasks, but sometimes appears a need in big numbers: for cryptography, IPv6, very big counters etc. Non-standard type __int128 which is provided by gcc and clang illuminates this need. But there is no cross-platform solution and no way to satisfy future needs in even more big numbers.
This is an attempt to solve the problem in a generic way on a library level and provide wording for P0104R0: Multi-Word Integer Operations and Types.
A proof of concept implementation available at: https://github.com/cerevra/int/tree/master/v2.
Differences with P0104R0:
int words
to size_t Bytes, bool Signed
in attempt to make the class less platform dependent (avoid description of "machine word" term and it's size) and in attept to minimize wording size by describing only one class, instead of two.common_type_t
of two types instead of a left-hand side type. This makes the wide_int
class behave more close to the built-in types.Extensions to P0104R0:
wide_int
class usage.wide_int
class with existing code.namespace std { // 26.??.2 class template wide_int template<size_t Bytes, bool Signed> class wide_int; // 26.??.?? type traits specializations template<size_t Bytes, bool Signed> struct is_scalar<wide_int<Bytes, Signed>>: true_type {}; template<size_t Bytes, bool Signed> struct is_compound<wide_int<Bytes, Signed>>: true_type {}; template<size_t Bytes, bool Signed> struct is_unsigned<wide_int<Bytes, Signed>>: bool_constant<!Signed> {}; template<size_t Bytes, bool Signed> struct is_signed<wide_int<Bytes, Signed>>: bool_constant<Signed> {}; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> struct common_type<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>>; template<size_t Bytes, bool Signed, typename Arithmetic> struct common_type<wide_int<Bytes, Signed>, Arithmetic>; // 26.??.?? unary operations template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator~(const wide_int<Bytes, Signed>& val) noexcept; template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator-(const wide_int<Bytes, Signed>& val) noexcept(!Signed); template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator+(const wide_int<Bytes, Signed>& val) noexcept(!Signed); // 26.??.?? binary operations template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator*(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator*(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator*(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator/(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator/(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator/(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator+(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator+(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator+(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator-(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator-(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator-(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator%(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs); template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator%(const wide_int<Bytes, Signed>& lhs, const Integral& rhs); template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator%(const Integral& lhs, const wide_int<Bytes, Signed>& rhs); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator&(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator&(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator&(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator|(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator|(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator|(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator^(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator^(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator^(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator<<(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs); template<size_t Bytes, bool Signed, typename Integral> constexpr wide_int<Bytes, Signed> operator<<(const wide_int<Bytes, Signed>& lhs, const Integral& rhs); template<size_t Bytes, bool Signed, typename Integral> constexpr Integral operator<<(const Integral& lhs, const wide_int<Bytes, Signed>& rhs); template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator>>(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> constexpr wide_int<Bytes, Signed> operator>>(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> constexpr Integral operator>>(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator<(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator>(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator<=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator>=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator==(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator==(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator==(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator!=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator!=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator!=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept; // 26.??.?? numeric conversions template<size_t Bytes, bool Signed> std::string to_string(const wide_int<Bytes, Signed>& val); template<size_t Bytes, bool Signed> std::wstring to_wstring(const wide_int<Bytes, Signed>& val); // 26.??.?? iostream specializations template<class Char, class Traits, size_t Bytes, bool Signed> basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os, const wide_int<Bytes, Signed>& val); template<class Char, class Traits, size_t Bytes, bool Signed> basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is, wide_int<Bytes, Signed>& val); using int128_t = wide_int<128 / 8,true>; using uint128_t = wide_int<128 / 8,false>; using int256_t = wide_int<256 / 8,true>; using uint256_t = wide_int<256 / 8,false>; using int512_t = wide_int<512 / 8,true>; using uint512_t = wide_int<512 / 8,false>; // 26.??.?? hash support template<class T> struct hash; template<size_t Bytes, bool Signed> struct hash<wide_int<Bytes, Signed>>; // 26.??.?? numeric_limits specialization template<size_t Bytes, bool Signed> struct numeric_limits<wide_int<Bytes, Signed>>; inline namespace literals { inline namespace wide_int_literals { constexpr int128_t operator "" _int128(const char*); constexpr int256_t operator "" _int256(const char*); constexpr int512_t operator "" _int512(const char*); constexpr uint128_t operator "" _uint128(const char*); constexpr uint256_t operator "" _uint256(const char*); constexpr uint512_t operator "" _uint512(const char*); } // namespace wide_int_literals } // namespace literals }
The header <wide_int> defines class template wide_int
and a set of operators for representing and manipulating integers of specified width.
[Example: constexpr int128_t c = std::numeric_limits<int128_t>::min(); static_assert(c == 0x80000000000000000000000000000000_uint128); int256_t a = 13; a += 0xFF; a *= 2.0; a -= 12_int128; assert(a > 0); ]
namespace std { template<size_t Bytes, bool Signed> class wide_int { public: // 26.??.2.?? construct: constexpr wide_int() noexcept = default; template<typename Arithmetic> constexpr wide_int(const Arithmetic& other) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int(const wide_int<Bytes2, Signed2>& other) noexcept; // 26.??.2.?? assignment: template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator=(const Arithmetic& other) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator=(const wide_int<Bytes2, Signed2>& other) noexcept; // 26.??.2.?? compound assignment: template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator*=(const Arithmetic&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator*=(const wide_int<Bytes2, Signed2>&); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator/=(const Arithmetic&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator/=(const wide_int<Bytes2, Signed2>&); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator+=(const Arithmetic&) noexcept(!Signed); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator+=(const wide_int<Bytes2, Signed2>&) noexcept(!Signed); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator-=(const Arithmetic&) noexcept(!Signed); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator-=(const wide_int<Bytes2, Signed2>&) noexcept(!Signed); template<typename Integral> constexpr wide_int<Bytes, Signed>& operator%=(const Integral&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator%=(const wide_int<Bytes2, Signed2>&); template<typename Integral> constexpr wide_int<Bytes, Signed>& operator&=(const Integral&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator&=(const wide_int<Bytes2, Signed2>&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator|=(const Integral&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator|=(const wide_int<Bytes2, Signed2>&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator^=(const Integral&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator^=(const wide_int<Bytes2, Signed2>&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator<<=(const Integral&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator<<=(const wide_int<Bytes2, Signed2>&); template<typename Integral> constexpr wide_int<Bytes, Signed>& operator>>=(const Integral&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator>>=(const wide_int<Bytes2, Signed2>&) noexcept; // 26.??.2.?? observers: template <typename Arithmetic> constexpr operator Arithmetic() const noexcept; constexpr explicit operator bool() const noexcept; private: uint32_t data[Bytes / sizeof(uint32_t) + 1]; // exposition only }; }
The class template wide_int<size_t Bytes, bool Signed>
is a POD class that behaves as an integer type of a compile time specified width. Template parameter Bytes
specifies significant bytes count to store the integer value. [Note: sizeof(wide_int<Bytes, true>)
and sizeof(wide_int<Bytes, false>)
are not requred to be equal to Bytes
. - end note] Template parameter Signed
specifies signedness of the stored integer value.
constexpr wide_int() noexcept = default;
template<typename Arithmetic> constexpr wide_int(const Arithmetic& other) noexcept;
is_arithmetic_v<Arithmetic>
is true.other
using the integral conversion rules [conv.integral].template<size_t Bytes2, bool Signed2> constexpr wide_int(const wide_int<Bytes2, Signed2>& other) noexcept;
other
using the integral conversion rules [conv.integral].template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator=(const Arithmetic& other) noexcept;
is_arithmetic_v<Arithmetic>
is true.other
using the integral conversion rules [conv.integral].template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator=(const wide_int<Bytes2, Signed2>& other) noexcept;
other
using the integral conversion rules [conv.integral].template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator*=(const wide_int<Bytes2, Signed2>&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator/=(const wide_int<Bytes2, Signed2>&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator+=(const wide_int<Bytes2, Signed2>&) noexcept(!Signed); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator-=(const wide_int<Bytes2, Signed2>&) noexcept(!Signed); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator%=(const wide_int<Bytes2, Signed2>&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator&=(const wide_int<Bytes2, Signed2>&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator|=(const wide_int<Bytes2, Signed2>&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator^=(const wide_int<Bytes2, Signed2>&) noexcept; template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator<<=(const wide_int<Bytes2, Signed2>&); template<size_t Bytes2, bool Signed2> constexpr wide_int<Bytes, Signed>& operator>>=(const wide_int<Bytes2, Signed2>&) noexcept;
template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator*=(const Arithmetic&); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator/=(const Arithmetic&); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator+=(const Arithmetic&) noexcept(!Signed); template<typename Arithmetic> constexpr wide_int<Bytes, Signed>& operator-=(const Arithmetic&) noexcept(!Signed);
is_arithmetic_v<Arithmetic>
is true.wi
of type wide_int<Bytes, Signed>
was created from input value and the corresponding operator was called for *this
and the wi
.template<typename Integral> constexpr wide_int<Bytes, Signed>& operator%=(const Integral&); template<typename Integral> constexpr wide_int<Bytes, Signed>& operator&=(const Integral&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator|=(const Integral&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator^=(const Integral&) noexcept; template<typename Integral> constexpr wide_int<Bytes, Signed>& operator<<=(const Integral&); template<typename Integral> constexpr wide_int<Bytes, Signed>& operator>>=(const Integral&) noexcept;
is_integral_v<Integral>
is true.wi
of type wide_int<Bytes, Signed>
was created from input value and the corresponding operator was called for *this
and the wi
.template <typename Arithmetic> constexpr operator Arithmetic() const noexcept;
is_arithmetic_v<Arithmetic>
is true.Arithmetic
type is an integral type then it is constructed from *this
using the integral conversion rules [conv.integral]. Otherwise Arithmetic
is constructed from *this
using the floating-integral conversion rules [conv.fpint].constexpr explicit operator bool() const noexcept;
true
if *this
is not equal to 0.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> struct common_type<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> { using type = wide_int<max(Bytes, Bytes2), see below>; };
The signed template parameter indicated by this specialization is following:
(Signed && Signed2)
if Bytes == Bytes2
Signed
if Bytes > Bytes2
Signed2
otherwisetemplate<size_t Bytes, bool Signed, typename Arithmetic> struct common_type<wide_int<Bytes, Signed>, Arithmetic> { using type = see below; };
The member typedef type
is following:
Arithmetic
if is_floating_point_v<Arithmetic>
is true
wide_int<Bytes, Signed>
if Bytes > sizeof(Arithmetic)
Arithmetic
if Bytes < sizeof(Arithmetic)
Arithmetic
if Bytes == sizeof(Arithmetic) && Signed
or Bytes == sizeof(Arithmetic) && Signed == is_signed_v<Arithmetic>
wide_int<Bytes, Signed>
otherwiseis_arithmetic_v<Arithmetic>
is true.template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator~(const wide_int<Bytes, Signed>& val) noexcept;
val
.template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator-(const wide_int<Bytes, Signed>& val) noexcept(!Signed);
val *= -1
if Signed
is true, otherwise the result is unspecified.template<size_t Bytes, bool Signed> constexpr wide_int<Bytes, Signed> operator+(const wide_int<Bytes, Signed>& val) noexcept(!Signed);
val
.In the function descriptions that follow, CT
represents common_type_t<A, B>
, where A
and B
are the types of the two arguments to the function.
Functions that accept Integral
parameter shall not participate in overload resolution unless is_integral_v<Integral>
is true.
Functions that accept Arithmetic
parameter shall not participate in overload resolution unless is_arithmetic_v<Arithmetic>
is true.
[Note: To reduce template instantinations count operators that accept Integral
and Arithmetic
parameter convert to common type first, as the common type may be a built-in type. - end note]
template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator*(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs);
CT(lhs) *= rhs
.template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator*(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator*(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs);
CT(lhs) * CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator/(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs);
CT(lhs) /= rhs
.template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator/(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator/(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs);
CT(lhs) / CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator+(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept(!Signed);
CT(lhs) += rhs
.template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator+(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator+(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept(!Signed);
CT(lhs) + CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator-(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept(!Signed);
CT(lhs) -= rhs
.template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator-(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept(!Signed); template<size_t Bytes, bool Signed, typename Arithmetic> common_type_t<wide_int<Bytes, Signed>, Arithmetic> constexpr operator-(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept(!Signed);
CT(lhs) - CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator%(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs);
CT(lhs) %= rhs
.template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator%(const wide_int<Bytes, Signed>& lhs, const Integral& rhs); template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator%(const Integral& lhs, const wide_int<Bytes, Signed>& rhs);
CT(lhs) % CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator&(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
CT(lhs) &= rhs
.template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator&(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator&(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) & CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator|(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
CT(lhs) |= rhs
.template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator|(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator|(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) | CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator^(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
CT(lhs) ^= rhs
.template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator^(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept; template<size_t Bytes, bool Signed, typename Integral> common_type_t<wide_int<Bytes, Signed>, Integral> constexpr operator^(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) ^ CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator<<(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs);
CT(lhs) <<= rhs
.template<size_t Bytes, bool Signed, typename Integral> constexpr wide_int<Bytes, Signed> operator<<(const wide_int<Bytes, Signed>& lhs, const Integral& rhs);
CT(lhs) << CT(rhs)
.template<size_t Bytes, bool Signed, typename Integral> constexpr Integral operator<<(const Integral& lhs, const wide_int<Bytes, Signed>& rhs);
lhs << Integral(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> common_type_t<wide_int<Bytes, Signed>, wide_int<Bytes2, Signed2>> constexpr operator>>(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
CT(lhs) >>= rhs
.template<size_t Bytes, bool Signed, typename Integral> constexpr wide_int<Bytes, Signed> operator>>(const wide_int<Bytes, Signed>& lhs, const Integral& rhs) noexcept;
CT(lhs) >> CT(rhs)
.template<size_t Bytes, bool Signed, typename Integral> constexpr Integral operator>>(const Integral& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
lhs >> Integral(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator<(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
true
if value of CT(lhs)
is less than the value of CT(rhs)
.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) < CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator>(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
true
if value of CT(lhs)
is greater than the value of CT(rhs)
.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) > CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator<=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
true
if value of CT(lhs)
is equal or less than the value of CT(rhs)
.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator<=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) <= CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator>=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
true
if value of CT(lhs)
is equal or greater than the value of CT(rhs)
.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator>=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) >= CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator==(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
true
if significant bits of CT(lhs)
and CT(rhs)
are the same.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator==(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator==(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) == CT(rhs)
.template<size_t Bytes, bool Signed, size_t Bytes2, bool Signed2> constexpr bool operator!=(const wide_int<Bytes, Signed>& lhs, const wide_int<Bytes2, Signed2>& rhs) noexcept;
!(CT(lhs) == CT(rhs))
.template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator!=(const wide_int<Bytes, Signed>& lhs, const Arithmetic& rhs) noexcept; template<size_t Bytes, bool Signed, typename Arithmetic> constexpr bool operator!=(const Arithmetic& lhs, const wide_int<Bytes, Signed>& rhs) noexcept;
CT(lhs) != CT(rhs)
.template<size_t Bytes, bool Signed> std::string to_string(const wide_int<Bytes, Signed>& val); template<size_t Bytes, bool Signed> std::wstring to_wstring(const wide_int<Bytes, Signed>& val);
[-]dddd
.template<class Char, class Traits, size_t Bytes, bool Signed> basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os, const wide_int<Bytes, Signed>& val);
os << to_string(val)
.os
.template<class Char, class Traits, size_t Bytes, bool Signed> basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is, wide_int<Bytes, Signed>& val);
wide_int
that is represented as a decimal number in the is
. If bad input is encountered, calls is.setstate(ios_base::failbit)
(which may throw ios::failure
([iostate.flags])).is
.template<size_t Bytes, bool Signed> struct hash<wide_int<Bytes, Signed>>;
The specialization is enabled (20.14.14). If there is a built-in integral type Integral
that has the same signedness and width as wide_int<Bytes, Signed>
, and wi
is an object of type wide_int<Bytes, Signed>
, then hash<wide_int<Bytes, Signed>>()(wi) == hash<Integral>()(Integral(wi))
.
template<size_t Bytes, bool Signed> struct numeric_limits<wide_int<Bytes, Signed>>;
Specialization follows the rules described in [numeric.limits.members]. If there is a built-in integral type Integral
that has the same signedness and width as wide_int<Bytes, Signed>
, then numeric_limits<wide_int<Bytes, Signed>>
specialized in the same way as numeric_limits<Integral>
.
For the purposes of SG10 it is sufficient to check for header <wide_int>
using __has_include
.