HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tagged_id.hpp
1// Copyright Take Vos 2020-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "utility.hpp"
8#include "cast.hpp"
9#include "math.hpp"
10#include "fixed_string.hpp"
11#include "concepts.hpp"
12#include <limits>
13#include <typeinfo>
14#include <typeindex>
15#include <compare>
16#include <concepts>
17
18namespace hi::inline v1 {
19
20template<std::unsigned_integral T, fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
21class tagged_id {
22public:
23 static_assert(Max < std::numeric_limits<T>::max(), "Max must be at least one less than the maximum value of T");
24
25 using value_type = T;
26
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);
30
31 constexpr tagged_id() noexcept : value(invalid) {}
32 constexpr tagged_id(tagged_id const &other) noexcept = default;
33 constexpr tagged_id(tagged_id &&other) noexcept = default;
34 constexpr tagged_id &operator=(tagged_id const &other) noexcept = default;
35 constexpr tagged_id &operator=(tagged_id &&other) noexcept = default;
36
37 constexpr explicit tagged_id(numeric_integral auto rhs) noexcept : value(narrow_cast<value_type>(rhs))
38 {
39 hi_axiom(holds_invariant() and value != invalid);
40 }
41
42 constexpr tagged_id &operator=(numeric_integral auto rhs) noexcept
43 {
44 value = narrow_cast<value_type>(rhs);
45 hi_axiom(holds_invariant() and value != invalid);
46 return *this;
47 }
48
49 constexpr tagged_id &operator=(std::monostate) noexcept
50 {
51 value = invalid;
52 return *this;
53 }
54
55 template<numeric_integral O>
56 constexpr explicit operator O() const noexcept
57 {
58 hi_axiom(value != invalid);
59 return narrow_cast<O>(value);
60 }
61
62 constexpr explicit operator bool() const noexcept
63 {
64 return value != invalid;
65 }
66
67 [[nodiscard]] constexpr value_type const &operator*() const noexcept
68 {
69 return value;
70 }
71
72 [[nodiscard]] constexpr std::size_t hash() const noexcept
73 {
74 return std::hash<value_type>{}(value);
75 }
76
77 [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, tagged_id const &rhs) noexcept
78 {
79 return lhs.value == rhs.value;
80 }
81
82 [[nodiscard]] constexpr friend std::partial_ordering operator<=>(tagged_id const &lhs, tagged_id const &rhs) noexcept
83 {
84 if (lhs.value == invalid or rhs.value == invalid) {
85 return std::partial_ordering::unordered;
86 } else {
87 return lhs.value <=> rhs.value;
88 }
89 }
90
91 [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, std::integral auto const &rhs) noexcept
92 {
93 return lhs == tagged_id{rhs};
94 }
95
96 [[nodiscard]] constexpr friend bool operator==(numeric_integral auto const &lhs, tagged_id const &rhs) noexcept
97 {
98 return tagged_id{lhs} == rhs;
99 }
100
101 [[nodiscard]] constexpr friend std::partial_ordering
102 operator<=>(tagged_id const &lhs, numeric_integral auto const &rhs) noexcept
103 {
104 return lhs <=> tagged_id{rhs};
105 }
106
107 [[nodiscard]] constexpr friend std::partial_ordering
108 operator<=>(numeric_integral auto const &lhs, tagged_id const &rhs) noexcept
109 {
110 return tagged_id{lhs} <=> rhs;
111 }
112
113 [[nodiscard]] bool holds_invariant() const noexcept
114 {
115 return value <= max or value == invalid;
116 }
117
118 [[nodiscard]] friend std::string to_string(tagged_id const &rhs) noexcept
119 {
120 return std::format("{}:{}", Tag, rhs.value);
121 }
122
123 friend std::ostream &operator<<(std::ostream &lhs, tagged_id const &rhs)
124 {
125 return lhs << to_string(rhs);
126 }
127
128private:
129 value_type value;
130};
131
132} // namespace hi::inline v1
133
134template<typename T, hi::fixed_string Tag, hi::ssize_t Max>
135struct std::hash<hi::tagged_id<T, Tag, Max>> {
136 [[nodiscard]] constexpr std::size_t operator()(hi::tagged_id<T, Tag, Max> const &rhs) const noexcept
137 {
138 return rhs.hash();
139 }
140};
#define hi_axiom(expression)
Specify an axiom; an expression that is true.
Definition assert.hpp:133
Miscellaneous math functions.
Utilities used by the HikoGUI library itself.
DOXYGEN BUG.
Definition algorithm.hpp:15
The HikoGUI namespace.
Definition ascii.hpp:19
Definition tagged_id.hpp:21
Definition concepts.hpp:24
T operator()(T... args)