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/module.hpp"
8#include <limits>
9#include <typeinfo>
10#include <typeindex>
11#include <compare>
12#include <concepts>
13
14namespace hi::inline v1 {
15
16template<std::unsigned_integral T, fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
17class tagged_id {
18public:
19 static_assert(Max < std::numeric_limits<T>::max(), "Max must be at least one less than the maximum value of T");
20
21 using value_type = T;
22
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);
26
27 constexpr tagged_id() noexcept : value(invalid) {}
28 constexpr tagged_id(tagged_id const& other) noexcept = default;
29 constexpr tagged_id(tagged_id&& other) noexcept = default;
30 constexpr tagged_id& operator=(tagged_id const& other) noexcept = default;
31 constexpr tagged_id& operator=(tagged_id&& other) noexcept = default;
32
33 constexpr explicit tagged_id(std::integral auto rhs) noexcept : value(narrow_cast<value_type>(rhs))
34 {
35 hi_axiom(holds_invariant() and value != invalid);
36 }
37
38 constexpr tagged_id(std::nullopt_t) noexcept : value(invalid) {}
39
40 constexpr tagged_id(nullptr_t) noexcept : value(invalid) {}
41
42 constexpr tagged_id& operator=(std::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::nullopt_t) noexcept
50 {
51 value = invalid;
52 return *this;
53 }
54
55 constexpr tagged_id& operator=(nullptr_t) noexcept
56 {
57 value = invalid;
58 return *this;
59 }
60
61 template<numeric_integral O>
62 constexpr explicit operator O() const noexcept
63 {
64 hi_axiom(value != invalid);
65 return narrow_cast<O>(value);
66 }
67
68 constexpr explicit operator bool() const noexcept
69 {
70 return value != invalid;
71 }
72
73 [[nodiscard]] constexpr value_type const& operator*() const noexcept
74 {
75 return value;
76 }
77
78 [[nodiscard]] constexpr std::size_t hash() const noexcept
79 {
80 return std::hash<value_type>{}(value);
81 }
82
83 [[nodiscard]] constexpr bool operator==(tagged_id const&) const noexcept = default;
84
85 [[nodiscard]] constexpr bool operator==(nullptr_t) const noexcept
86 {
87 return value == invalid;
88 }
89
90 [[nodiscard]] constexpr bool operator==(std::nullopt_t) const noexcept
91 {
92 return value == invalid;
93 }
94
95 // clang-format off
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; }
106 // clang-format on
107
108 [[nodiscard]] bool holds_invariant() const noexcept
109 {
110 return value <= max or value == invalid;
111 }
112
113 [[nodiscard]] friend std::string to_string(tagged_id const& rhs) noexcept
114 {
115 return std::format("{}:{}", Tag, rhs.value);
116 }
117
118 friend std::ostream& operator<<(std::ostream& lhs, tagged_id const& rhs)
119 {
120 return lhs << to_string(rhs);
121 }
122
123private:
124 value_type value;
125};
126
127} // namespace hi::inline v1
128
129template<typename T, hi::fixed_string Tag, hi::ssize_t Max>
130struct std::hash<hi::tagged_id<T, Tag, Max>> {
131 [[nodiscard]] constexpr std::size_t operator()(hi::tagged_id<T, Tag, Max> const& rhs) const noexcept
132 {
133 return rhs.hash();
134 }
135};
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:238
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
Definition tagged_id.hpp:17
T operator()(T... args)