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 "terminate.hpp"
9#include <limits>
10#include <typeinfo>
11#include <typeindex>
12#include <compare>
13#include <concepts>
14#include <bit>
15#include <optional>
16#include <string>
17#include <ostream>
18#include <cstddef>
19
20hi_export_module(hikogui.utility.tagged_id);
21
22hi_export namespace hi::inline v1 {
23
24namespace detail {
25
26template<typename Derived, std::unsigned_integral T, T Empty>
27std::atomic<T> tagged_id_counter = Empty == 0 ? T{1} : T{0};
28
29}
30
38template<typename Derived, std::unsigned_integral T, T Empty>
39class tagged_id {
40public:
41 using derived_type = Derived;
42 using value_type = T;
43 constexpr static value_type empty_value = Empty;
44
45 constexpr tagged_id() noexcept = default;
46 constexpr tagged_id(tagged_id const& other) noexcept = default;
47 constexpr tagged_id(tagged_id&& other) noexcept = default;
48 constexpr tagged_id& operator=(tagged_id const& other) noexcept = default;
49 constexpr tagged_id& operator=(tagged_id&& other) noexcept = default;
50 constexpr tagged_id(std::nullopt_t) noexcept : _v(empty_value) {}
51
52 constexpr tagged_id(value_type rhs) : _v(rhs) {
53 if (rhs == empty_value) {
54 throw std::overflow_error("The given identifier was the empty-value");
55 }
56 }
57
60 [[nodiscard]] static tagged_id make()
61 {
62 return detail::tagged_id_counter<derived_type, value_type, empty_value>.fetch_add(1, std::memory_order::relaxed);
63 }
64
65 constexpr tagged_id& operator=(value_type rhs)
66 {
67 if (rhs == empty_value) {
68 throw std::overflow_error("The given identifier was the empty-value");
69 }
70
71 _v = rhs;
72 return *this;
73 }
74
75 constexpr tagged_id& operator=(std::nullopt_t) noexcept
76 {
77 _v = empty_value;
78 return *this;
79 }
80
81 [[nodiscard]] constexpr bool empty() const noexcept
82 {
83 return _v == empty_value;
84 }
85
86 constexpr explicit operator bool() const noexcept
87 {
88 return not empty();
89 }
90
91 [[nodiscard]] constexpr value_type value() const
92 {
93 if (_v == empty_value) {
94 throw std::overflow_error("Dereferencing an empty identifier");
95 }
96 return _v;
97 }
98
99 constexpr explicit operator value_type() const
100 {
101 return value();
102 }
103
104 [[nodiscard]] constexpr value_type operator*() const
105 {
106 return value();
107 }
108
109 [[nodiscard]] constexpr friend auto operator<=>(tagged_id const&, tagged_id const &) noexcept = default;
110 [[nodiscard]] constexpr friend bool operator==(tagged_id const&, tagged_id const &) noexcept = default;
111
112private:
113 value_type _v = empty_value;
114};
115
116} // namespace hi::inline v1
117
118hi_export template<typename Derived, std::unsigned_integral T, T Empty>
119struct std::hash<hi::tagged_id<Derived, T, Empty>> {
120 [[nodiscard]] constexpr std::size_t operator()(hi::tagged_id<Derived, T, Empty> const& rhs) const noexcept
121 {
122 return std::hash<T>{}(rhs.value());
123 }
124};
Utilities for throwing exceptions and terminating the application.
The HikoGUI namespace.
Definition array_generic.hpp:21
constexpr matrix2 operator*(matrix2 const &lhs, matrix2 const &rhs) noexcept
Matrix/Matrix multiplication.
Definition transform.hpp:69
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
A tagged identifier.
Definition tagged_id.hpp:39
static tagged_id make()
Make a new unique identifier.
Definition tagged_id.hpp:60
T operator()(T... args)