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 "../macros.hpp"
8#include "fixed_string.hpp"
9#include <limits>
10#include <typeinfo>
11#include <typeindex>
12#include <compare>
13#include <concepts>
14
15hi_export_module(hikogui.utility.tagged_id);
16
17hi_export namespace hi::inline v1 {
18
20class tagged_id {
21public:
22 static_assert(Max < std::numeric_limits<T>::max(), "Max must be at least one less than the maximum value of T");
23
24 using value_type = T;
25
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);
29
30 constexpr tagged_id() noexcept : value(invalid) {}
31 constexpr tagged_id(tagged_id const& other) noexcept = default;
32 constexpr tagged_id(tagged_id&& other) noexcept = default;
33 constexpr tagged_id& operator=(tagged_id const& other) noexcept = default;
34 constexpr tagged_id& operator=(tagged_id&& other) noexcept = default;
35
36 constexpr explicit tagged_id(std::integral auto rhs) noexcept : value(narrow_cast<value_type>(rhs))
37 {
38 hi_axiom(holds_invariant() and value != invalid);
39 }
40
41 constexpr tagged_id(std::nullopt_t) noexcept : value(invalid) {}
42
43 constexpr tagged_id(nullptr_t) noexcept : value(invalid) {}
44
45 constexpr tagged_id& operator=(std::integral auto rhs) noexcept
46 {
47 value = narrow_cast<value_type>(rhs);
48 hi_axiom(holds_invariant() and value != invalid);
49 return *this;
50 }
51
52 constexpr tagged_id& operator=(std::nullopt_t) noexcept
53 {
54 value = invalid;
55 return *this;
56 }
57
58 constexpr tagged_id& operator=(nullptr_t) noexcept
59 {
60 value = invalid;
61 return *this;
62 }
63
64 template<numeric_integral O>
65 constexpr explicit operator O() const noexcept
66 {
67 hi_axiom(value != invalid);
68 return narrow_cast<O>(value);
69 }
70
71 constexpr explicit operator bool() const noexcept
72 {
73 return value != invalid;
74 }
75
76 [[nodiscard]] constexpr value_type const& operator*() const noexcept
77 {
78 return value;
79 }
80
81 [[nodiscard]] constexpr std::size_t hash() const noexcept
82 {
83 return std::hash<value_type>{}(value);
84 }
85
86 [[nodiscard]] constexpr bool operator==(tagged_id const&) const noexcept = default;
87
88 [[nodiscard]] constexpr bool operator==(nullptr_t) const noexcept
89 {
90 return value == invalid;
91 }
92
93 [[nodiscard]] constexpr bool operator==(std::nullopt_t) const noexcept
94 {
95 return value == invalid;
96 }
97
98 // clang-format off
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; }
109 // clang-format on
110
111 [[nodiscard]] bool holds_invariant() const noexcept
112 {
113 return value <= max or value == invalid;
114 }
115
116 [[nodiscard]] friend std::string to_string(tagged_id const& rhs) noexcept
117 {
118 return std::format("{}:{}", Tag, rhs.value);
119 }
120
121 friend std::ostream& operator<<(std::ostream& lhs, tagged_id const& rhs)
122 {
123 return lhs << to_string(rhs);
124 }
125
126private:
127 value_type value;
128};
129
130} // namespace hi::inline v1
131
132template<typename T, hi::fixed_string Tag, hi::ssize_t Max>
133struct std::hash<hi::tagged_id<T, Tag, Max>> {
134 [[nodiscard]] constexpr std::size_t operator()(hi::tagged_id<T, Tag, Max> const& rhs) const noexcept
135 {
136 return rhs.hash();
137 }
138};
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Definition tagged_id.hpp:20
T operator()(T... args)