HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tagged_id.hpp
1// Copyright Take Vos 2020.
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 "required.hpp"
8#include "cast.hpp"
9#include "math.hpp"
10#include "fixed_string.hpp"
11#include <limits>
12#include <typeinfo>
13#include <typeindex>
14
15namespace tt {
16
17template<typename T, basic_fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
18class tagged_id {
19public:
20 static_assert(std::is_integral_v<T>, "Expecting tagged_id to be an integral");
21 static_assert(std::is_unsigned_v<T>, "Expecting tagged_id to be an unsigned integer");
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 explicit tagged_id(signed long long rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
31 constexpr explicit tagged_id(signed long rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
32 constexpr explicit tagged_id(signed int rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
33 constexpr explicit tagged_id(signed short rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
34 constexpr explicit tagged_id(signed char rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
35 constexpr explicit tagged_id(unsigned long long rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
36 constexpr explicit tagged_id(unsigned long rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
37 constexpr explicit tagged_id(unsigned int rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
38 constexpr explicit tagged_id(unsigned short rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
39 constexpr explicit tagged_id(unsigned char rhs) noexcept : value(narrow_cast<value_type>(rhs)) { tt_axiom(value <= invalid); }
40
41 constexpr tagged_id &operator=(signed long long rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
42 constexpr tagged_id &operator=(signed long rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
43 constexpr tagged_id &operator=(signed int rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
44 constexpr tagged_id &operator=(signed short rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
45 constexpr tagged_id &operator=(signed char rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
46 constexpr tagged_id &operator=(unsigned long long rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
47 constexpr tagged_id &operator=(unsigned long rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
48 constexpr tagged_id &operator=(unsigned int rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
49 constexpr tagged_id &operator=(unsigned short rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
50 constexpr tagged_id &operator=(unsigned char rhs) noexcept { value = narrow_cast<value_type>(rhs); tt_axiom(value <= invalid); return *this; }
51
52 constexpr tagged_id() noexcept : value(invalid) {}
53 constexpr tagged_id(tagged_id const &other) noexcept = default;
54 constexpr tagged_id(tagged_id &&other) noexcept = default;
55 constexpr tagged_id &operator=(tagged_id const &other) noexcept = default;
56 constexpr tagged_id &operator=(tagged_id &&other) noexcept = default;
57
58 constexpr operator signed long long () const noexcept { return narrow_cast<signed long long>(value); }
59 constexpr operator signed long () const noexcept { return narrow_cast<signed long>(value); }
60 constexpr operator signed int () const noexcept { return narrow_cast<signed int>(value); }
61 constexpr operator signed short () const noexcept { return narrow_cast<signed short>(value); }
62 constexpr operator signed char () const noexcept { return narrow_cast<signed char>(value); }
63 constexpr operator unsigned long long () const noexcept { return narrow_cast<unsigned long long>(value); }
64 constexpr operator unsigned long () const noexcept { return narrow_cast<unsigned long>(value); }
65 constexpr operator unsigned int () const noexcept { return narrow_cast<unsigned int>(value); }
66 constexpr operator unsigned short () const noexcept { return narrow_cast<unsigned short>(value); }
67 constexpr operator unsigned char () const noexcept { return narrow_cast<unsigned char>(value); }
68
69 constexpr operator bool () const noexcept { return value <= max; }
70
71 [[nodiscard]] constexpr size_t hash() const noexcept { return std::hash<value_type>{}(value); }
72
73 [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value == rhs.value; }
74 [[nodiscard]] constexpr friend bool operator!=(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value != rhs.value; }
75 [[nodiscard]] constexpr friend bool operator<(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value < rhs.value; }
76 [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value > rhs.value; }
77 [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value <= rhs.value; }
78 [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value >= rhs.value; }
79
80 template<typename O> [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, O const &rhs) noexcept { return lhs == tagged_id{rhs}; }
81 template<typename O> [[nodiscard]] constexpr friend bool operator!=(tagged_id const &lhs, O const &rhs) noexcept { return lhs != tagged_id{rhs}; }
82 template<typename O> [[nodiscard]] constexpr friend bool operator<(tagged_id const &lhs, O const &rhs) noexcept { return lhs < tagged_id{rhs}; }
83 template<typename O> [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, O const &rhs) noexcept { return lhs > tagged_id{rhs}; }
84 template<typename O> [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, O const &rhs) noexcept { return lhs <= tagged_id{rhs}; }
85 template<typename O> [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, O const &rhs) noexcept { return lhs >= tagged_id{rhs}; }
86 template<typename O> [[nodiscard]] constexpr friend bool operator==(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} == rhs; }
87 template<typename O> [[nodiscard]] constexpr friend bool operator!=(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} != rhs; }
88 template<typename O> [[nodiscard]] constexpr friend bool operator<(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} < rhs; }
89 template<typename O> [[nodiscard]] constexpr friend bool operator>(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} > rhs; }
90 template<typename O> [[nodiscard]] constexpr friend bool operator<=(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} <= rhs; }
91 template<typename O> [[nodiscard]] constexpr friend bool operator>=(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} >= rhs; }
92
93 [[nodiscard]] friend std::string to_string(tagged_id const &rhs) noexcept {
94 return fmt::format("{}:{}", Tag, rhs.value);
95 }
96
97 friend std::ostream &operator<<(std::ostream &lhs, tagged_id const &rhs) {
98 return lhs << to_string(rhs);
99 }
100
101private:
102 value_type value;
103
104};
105
106}
107
108namespace std {
109
110template<typename T, tt::basic_fixed_string Tag, tt::ssize_t Max>
111struct hash<tt::tagged_id<T,Tag,Max>> {
112 [[nodiscard]] constexpr size_t operator() (tt::tagged_id<T,Tag,Max> const &rhs) const noexcept {
113 return rhs.hash();
114 }
115};
116
117}
STL namespace.
Definition tagged_id.hpp:18
T operator()(T... args)