20template<std::unsigned_integral T, fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
23 static_assert(Max < std::numeric_limits<T>::max(),
"Max must be at least one less than the maximum value of T");
27 constexpr static value_type max = Max;
28 constexpr static value_type invalid = max + 1;
29 constexpr static value_type mask =
static_cast<value_type
>((1ULL << std::bit_width(invalid)) - 1);
31 constexpr tagged_id() noexcept : value(invalid) {}
39 hi_axiom(holds_invariant() and value != invalid);
44 value = narrow_cast<value_type>(rhs);
45 hi_axiom(holds_invariant() and value != invalid);
49 constexpr tagged_id &operator=(std::monostate)
noexcept
55 template<numeric_
integral O>
56 constexpr explicit operator O()
const noexcept
59 return narrow_cast<O>(value);
62 constexpr explicit operator bool()
const noexcept
64 return value != invalid;
67 [[nodiscard]]
constexpr value_type
const &operator*()
const noexcept
72 [[nodiscard]]
constexpr std::size_t hash()
const noexcept
77 [[nodiscard]]
constexpr friend bool operator==(
tagged_id const &lhs,
tagged_id const &rhs)
noexcept
79 return lhs.value == rhs.value;
82 [[nodiscard]]
constexpr friend std::partial_ordering operator<=>(
tagged_id const &lhs,
tagged_id const &rhs)
noexcept
84 if (lhs.value == invalid or rhs.value == invalid) {
85 return std::partial_ordering::unordered;
87 return lhs.value <=> rhs.value;
91 [[nodiscard]]
constexpr friend bool operator==(
tagged_id const &lhs, std::integral
auto const &rhs)
noexcept
101 [[nodiscard]]
constexpr friend std::partial_ordering
107 [[nodiscard]]
constexpr friend std::partial_ordering
113 [[nodiscard]]
bool holds_invariant()
const noexcept
115 return value <= max or value == invalid;
120 return std::format(
"{}:{}", Tag, rhs.value);
125 return lhs << to_string(rhs);
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:133