22 static_assert(Max < std::numeric_limits<T>::max(),
"Max must be at least one less than the maximum value of T");
26 constexpr static value_type max = Max;
27 constexpr static value_type invalid = max + 1;
28 constexpr static value_type mask =
static_cast<value_type
>((1ULL << std::bit_width(invalid)) - 1);
30 constexpr tagged_id() noexcept : value(invalid) {}
36 constexpr explicit tagged_id(std::integral
auto rhs) noexcept : value(narrow_cast<value_type>(rhs))
38 hi_axiom(holds_invariant() and value != invalid);
41 constexpr tagged_id(std::nullopt_t) noexcept : value(invalid) {}
43 constexpr tagged_id(nullptr_t) noexcept : value(invalid) {}
45 constexpr tagged_id& operator=(std::integral
auto rhs)
noexcept
47 value = narrow_cast<value_type>(rhs);
48 hi_axiom(holds_invariant() and value != invalid);
52 constexpr tagged_id& operator=(std::nullopt_t)
noexcept
58 constexpr tagged_id& operator=(nullptr_t)
noexcept
64 template<numeric_
integral O>
65 constexpr explicit operator O()
const noexcept
67 hi_axiom(value != invalid);
68 return narrow_cast<O>(value);
71 constexpr explicit operator bool()
const noexcept
73 return value != invalid;
76 [[nodiscard]]
constexpr value_type
const& operator*()
const noexcept
81 [[nodiscard]]
constexpr std::size_t hash()
const noexcept
86 [[nodiscard]]
constexpr bool operator==(
tagged_id const&)
const noexcept =
default;
88 [[nodiscard]]
constexpr bool operator==(nullptr_t)
const noexcept
90 return value == invalid;
93 [[nodiscard]]
constexpr bool operator==(std::nullopt_t)
const noexcept
95 return value == invalid;
99 [[nodiscard]]
constexpr bool operator==(
signed char rhs)
const noexcept {
return value == rhs; }
100 [[nodiscard]]
constexpr bool operator==(
signed short rhs)
const noexcept {
return value == rhs; }
101 [[nodiscard]]
constexpr bool operator==(
signed int rhs)
const noexcept {
return value == rhs; }
102 [[nodiscard]]
constexpr bool operator==(
signed long rhs)
const noexcept {
return value == rhs; }
103 [[nodiscard]]
constexpr bool operator==(
signed long long rhs)
const noexcept {
return value == rhs; }
104 [[nodiscard]]
constexpr bool operator==(
unsigned char rhs)
const noexcept {
return value == rhs; }
105 [[nodiscard]]
constexpr bool operator==(
unsigned short rhs)
const noexcept {
return value == rhs; }
106 [[nodiscard]]
constexpr bool operator==(
unsigned int rhs)
const noexcept {
return value == rhs; }
107 [[nodiscard]]
constexpr bool operator==(
unsigned long rhs)
const noexcept {
return value == rhs; }
108 [[nodiscard]]
constexpr bool operator==(
unsigned long long rhs)
const noexcept {
return value == rhs; }
111 [[nodiscard]]
bool holds_invariant()
const noexcept
113 return value <= max or value == invalid;
118 return std::format(
"{}:{}", Tag, rhs.value);
123 return lhs << to_string(rhs);