16template<std::unsigned_integral T, fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
19 static_assert(Max < std::numeric_limits<T>::max(),
"Max must be at least one less than the maximum value of T");
23 constexpr static value_type max = Max;
24 constexpr static value_type invalid = max + 1;
25 constexpr static value_type mask =
static_cast<value_type
>((1ULL << std::bit_width(invalid)) - 1);
27 constexpr tagged_id() noexcept : value(invalid) {}
33 constexpr explicit tagged_id(std::integral
auto rhs) noexcept : value(narrow_cast<value_type>(rhs))
35 hi_axiom(holds_invariant() and value != invalid);
38 constexpr tagged_id(std::nullopt_t) noexcept : value(invalid) {}
40 constexpr tagged_id(nullptr_t) noexcept : value(invalid) {}
42 constexpr tagged_id& operator=(std::integral
auto rhs)
noexcept
44 value = narrow_cast<value_type>(rhs);
45 hi_axiom(holds_invariant() and value != invalid);
49 constexpr tagged_id& operator=(std::nullopt_t)
noexcept
55 constexpr tagged_id& operator=(nullptr_t)
noexcept
61 template<numeric_
integral O>
62 constexpr explicit operator O()
const noexcept
65 return narrow_cast<O>(value);
68 constexpr explicit operator bool()
const noexcept
70 return value != invalid;
73 [[nodiscard]]
constexpr value_type
const& operator*()
const noexcept
78 [[nodiscard]]
constexpr std::size_t hash()
const noexcept
83 [[nodiscard]]
constexpr bool operator==(
tagged_id const&)
const noexcept =
default;
85 [[nodiscard]]
constexpr bool operator==(nullptr_t)
const noexcept
87 return value == invalid;
90 [[nodiscard]]
constexpr bool operator==(std::nullopt_t)
const noexcept
92 return value == invalid;
96 [[nodiscard]]
constexpr bool operator==(
signed char rhs)
const noexcept {
return value == rhs; }
97 [[nodiscard]]
constexpr bool operator==(
signed short rhs)
const noexcept {
return value == rhs; }
98 [[nodiscard]]
constexpr bool operator==(
signed int rhs)
const noexcept {
return value == rhs; }
99 [[nodiscard]]
constexpr bool operator==(
signed long rhs)
const noexcept {
return value == rhs; }
100 [[nodiscard]]
constexpr bool operator==(
signed long long rhs)
const noexcept {
return value == rhs; }
101 [[nodiscard]]
constexpr bool operator==(
unsigned char rhs)
const noexcept {
return value == rhs; }
102 [[nodiscard]]
constexpr bool operator==(
unsigned short rhs)
const noexcept {
return value == rhs; }
103 [[nodiscard]]
constexpr bool operator==(
unsigned int rhs)
const noexcept {
return value == rhs; }
104 [[nodiscard]]
constexpr bool operator==(
unsigned long rhs)
const noexcept {
return value == rhs; }
105 [[nodiscard]]
constexpr bool operator==(
unsigned long long rhs)
const noexcept {
return value == rhs; }
108 [[nodiscard]]
bool holds_invariant()
const noexcept
110 return value <= max or value == invalid;
115 return std::format(
"{}:{}", Tag, rhs.value);
120 return lhs << to_string(rhs);
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253