HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tagged_id.hpp
1// Copyright 2020 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/required.hpp"
7#include "TTauri/Foundation/string_tag.hpp"
8#include "TTauri/Foundation/numeric_cast.hpp"
9#include "TTauri/Foundation/math.hpp"
10#include <limits>
11#include <typeinfo>
12#include <typeindex>
13
14namespace tt {
15
16template<typename T, typename Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
17class tagged_id {
18public:
19 static_assert(std::is_integral_v<T>, "Expecting tagged_id to be an integral");
20 static_assert(Max < std::numeric_limits<T>::max(), "Max must be at least one less than the maximum value of T");
21
22 using type = T;
23 using TAG = Tag;
24
25 constexpr static type max = Max;
26 constexpr static type invalid = max + 1;
27
28 constexpr static type mask = make_mask(invalid);
29
30private:
31 type value;
32
33public:
34 constexpr explicit tagged_id(signed long long rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
35 constexpr explicit tagged_id(signed long rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
36 constexpr explicit tagged_id(signed int rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
37 constexpr explicit tagged_id(signed short rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
38 constexpr explicit tagged_id(signed char rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
39 constexpr explicit tagged_id(unsigned long long rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
40 constexpr explicit tagged_id(unsigned long rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
41 constexpr explicit tagged_id(unsigned int rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
42 constexpr explicit tagged_id(unsigned short rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
43 constexpr explicit tagged_id(unsigned char rhs) noexcept : value(numeric_cast<type>(rhs)) { tt_assume(value <= invalid); }
44
45 constexpr tagged_id &operator=(signed long long rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
46 constexpr tagged_id &operator=(signed long rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
47 constexpr tagged_id &operator=(signed int rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
48 constexpr tagged_id &operator=(signed short rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
49 constexpr tagged_id &operator=(signed char rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
50 constexpr tagged_id &operator=(unsigned long long rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
51 constexpr tagged_id &operator=(unsigned long rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
52 constexpr tagged_id &operator=(unsigned int rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
53 constexpr tagged_id &operator=(unsigned short rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
54 constexpr tagged_id &operator=(unsigned char rhs) noexcept { value = numeric_cast<type>(rhs); tt_assume(value <= invalid); return *this; }
55
56 constexpr tagged_id() noexcept : value(invalid) {}
57 constexpr tagged_id(tagged_id const &other) noexcept = default;
58 constexpr tagged_id(tagged_id &&other) noexcept = default;
59 constexpr tagged_id &operator=(tagged_id const &other) noexcept = default;
60 constexpr tagged_id &operator=(tagged_id &&other) noexcept = default;
61
62 constexpr operator signed long long () const noexcept { return numeric_cast<signed long long>(value); }
63 constexpr operator signed long () const noexcept { return numeric_cast<signed long>(value); }
64 constexpr operator signed int () const noexcept { return numeric_cast<signed int>(value); }
65 constexpr operator signed short () const noexcept { return numeric_cast<signed short>(value); }
66 constexpr operator signed char () const noexcept { return numeric_cast<signed char>(value); }
67 constexpr operator unsigned long long () const noexcept { return numeric_cast<unsigned long long>(value); }
68 constexpr operator unsigned long () const noexcept { return numeric_cast<unsigned long>(value); }
69 constexpr operator unsigned int () const noexcept { return numeric_cast<unsigned int>(value); }
70 constexpr operator unsigned short () const noexcept { return numeric_cast<unsigned short>(value); }
71 constexpr operator unsigned char () const noexcept { return numeric_cast<unsigned char>(value); }
72
73 constexpr operator bool () const noexcept { return value <= max; }
74
75 [[nodiscard]] constexpr size_t hash() const noexcept { return std::hash<type>{}(value); }
76
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 [[nodiscard]] constexpr friend bool operator<(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value < rhs.value; }
80 [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value > rhs.value; }
81 [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value <= rhs.value; }
82 [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, tagged_id const &rhs) noexcept { return lhs.value >= rhs.value; }
83
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<(tagged_id const &lhs, O const &rhs) noexcept { return lhs < tagged_id{rhs}; }
87 template<typename O> [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, O const &rhs) noexcept { return lhs > tagged_id{rhs}; }
88 template<typename O> [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, O const &rhs) noexcept { return lhs <= tagged_id{rhs}; }
89 template<typename O> [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, O const &rhs) noexcept { return lhs >= tagged_id{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 template<typename O> [[nodiscard]] constexpr friend bool operator<(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} < rhs; }
93 template<typename O> [[nodiscard]] constexpr friend bool operator>(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} > rhs; }
94 template<typename O> [[nodiscard]] constexpr friend bool operator<=(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} <= rhs; }
95 template<typename O> [[nodiscard]] constexpr friend bool operator>=(O const &lhs, tagged_id const &rhs) noexcept { return tagged_id{lhs} >= rhs; }
96
97 [[nodiscard]] friend std::string to_string(tagged_id const &rhs) noexcept {
98 return fmt::format("{}:{}", std::type_index(typeid(rhs.TAG)).name(), rhs.value);
99 }
100
101 friend std::ostream &operator<<(std::ostream &lhs, tagged_id const &rhs) {
102 return lhs << to_string(rhs);
103 }
104};
105
106}
107
108namespace std {
109
110template<typename T, typename 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:17
T name(T... args)
T operator()(T... args)