Symmetri
Loading...
Searching...
No Matches
colors.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <algorithm>
6#include <array> // std::array
7#include <cassert>
8#include <functional>
9#include <string_view>
10#include <type_traits>
11#include <utility> // std::index_sequence
12#include <vector>
13namespace symmetri {
14
15#ifndef DOXYGEN_SHOULD_SKIP_THIS
16
17// https://rodusek.com/posts/2021/03/09/getting-an-unmangled-type-name-at-compile-time/
18
19template <std::size_t... Idxs>
20constexpr auto substring_as_array(std::string_view str,
21 std::index_sequence<Idxs...>) {
22 return std::array{str[Idxs]...};
23}
24
25template <typename T>
26constexpr auto type_name_array() {
27#if defined(__clang__)
28 constexpr auto prefix = std::string_view{"[T = symmetri::"};
29 constexpr auto suffix = std::string_view{"]"};
30 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
31#elif defined(__GNUC__)
32 constexpr auto prefix = std::string_view{"with T = symmetri::"};
33 constexpr auto suffix = std::string_view{"]"};
34 constexpr auto function = std::string_view{__PRETTY_FUNCTION__};
35#elif defined(_MSC_VER)
36 constexpr auto prefix = std::string_view{"type_name_array<symmetri::"};
37 constexpr auto suffix = std::string_view{">(void)"};
38 constexpr auto function = std::string_view{__FUNCSIG__};
39#else
40#error Unsupported compiler
41#endif
42
43 constexpr auto start = function.find(prefix) + prefix.size();
44 constexpr auto end = function.rfind(suffix);
45
46 static_assert(start < end);
47
48 constexpr auto name = function.substr(start, (end - start));
49 return substring_as_array(name, std::make_index_sequence<name.size()>{});
50}
51
52template <typename T>
53struct type_name_holder {
54 static inline constexpr auto value = type_name_array<T>();
55};
56
57template <typename T>
58constexpr auto type_name() -> std::string_view {
59 constexpr auto& value = type_name_holder<T>::value;
60 return std::string_view{value.data(), value.size()};
61}
62
63template <auto Id>
64struct counter {
65 using tag = counter;
66
67 struct generator {
68 template <typename...>
69 friend constexpr auto is_defined(tag) {
70 return true;
71 }
72 };
73
74 template <typename...>
75 friend constexpr auto is_defined(tag);
76
77 template <typename Tag = tag, auto I = (int)is_defined(Tag{})>
78 static constexpr auto exists(decltype(I)) {
79 return true;
80 }
81
82 static constexpr auto exists(...) { return generator(), false; }
83};
84
85template <typename T, auto Id = int{}>
86constexpr auto unique_id() {
87 if constexpr (counter<Id>::exists(Id)) {
88 return unique_id<T, Id + 1>();
89 } else {
90 return Id;
91 }
92}
93
94#endif /* DOXYGEN_SHOULD_SKIP_THIS */
95
104class Token {
105 const static size_t kMaxTokenColors =
106 100;
107 size_t idx;
108 inline static std::array<std::string_view, kMaxTokenColors>
109 v{};
111
112 protected:
119 template <class T>
120 constexpr Token(T* const) : idx(unique_id<T>()) {
121 static_assert(unique_id<T>() < v.size(),
122 "There can only be 100 different token-colors.");
123 v[idx] = type_name<T>();
124 }
125
126 public:
134 Token(const char* s)
135 : idx([&]() -> size_t {
136 static size_t i = 0;
137 auto it = std::find(v.cbegin(), v.cend(), s);
138 if (it == std::cend(v)) {
139 i++;
140 return v.size() - i;
141 } else {
142 return std::distance(v.cbegin(), it);
143 }
144 }()) {
145 if (std::find(v.cbegin(), v.cend(), s) == std::cend(v)) {
146 assert(v[idx].empty() && "There can only be 100 different token-colors.");
147 v[idx] = s;
148 }
149 }
150
151 Token() = delete;
152
158 static std::vector<std::string_view> getColors() {
159 std::vector<std::string_view> colors;
160 colors.reserve(v.size());
161 std::copy_if(v.begin(), v.end(), std::back_inserter(colors),
162 [](const auto& color) { return not color.empty(); });
163 return colors;
164 }
165 constexpr bool operator<(const Token& rhs) const {
166 return idx < rhs.toIndex();
167 }
168 constexpr bool operator>(const Token& rhs) const {
169 return idx > rhs.toIndex();
170 }
176 constexpr size_t toIndex() const { return idx; }
177
183 constexpr const auto& toString() const { return v[idx]; }
184 constexpr bool operator==(const Token& c) const { return idx == c.idx; }
185 template <class T>
186 constexpr bool operator==(const T&) const {
187 return idx == unique_id<T>();
188 }
189};
190
191} // namespace symmetri
192
198#define CREATE_CUSTOM_TOKEN(name) \
199 namespace symmetri { \
200 struct name : public Token { \
201 constexpr name() : Token(this) {} \
202 constexpr bool operator==(const Token& c) const { \
203 return toIndex() == c.toIndex(); \
204 } \
205 }; \
206 static inline name name; \
207 }
208
Tokens are elements that can reside in places. Tokens can have a color which makes them distinguishab...
Definition colors.hpp:104
Token(const char *s)
Construct a new Token object from a string at run-time. A unique id is generated and if it fails it w...
Definition colors.hpp:134
static std::vector< std::string_view > getColors()
Get a list of all the colors.
Definition colors.hpp:158
constexpr const auto & toString() const
returns the string-representation for this color.
Definition colors.hpp:183
constexpr size_t toIndex() const
returns the unique index for this color.
Definition colors.hpp:176
constexpr Token(T *const)
Creates a Token with a unique numerical id and a string representation based on the name of the argum...
Definition colors.hpp:120
#define CREATE_CUSTOM_TOKEN(name)
A macro from which we can create token-colors. Colors ceated this way end up in the symmetri namespac...
Definition colors.hpp:198
Definition colors.hpp:213
Definition colors.hpp:212
Definition colors.hpp:215
Definition colors.hpp:214
Definition colors.hpp:209
Definition colors.hpp:210
Definition colors.hpp:211