libs/capy/include/boost/capy/detail/type_id.hpp

100.0% Lines (2/2) -% Functions (0/1) -% Branches (0/0)
libs/capy/include/boost/capy/detail/type_id.hpp
Line Hits Source Code
1 //
2 // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/capy
8 //
9
10 #ifndef BOOST_CAPY_DETAIL_TYPE_ID_HPP
11 #define BOOST_CAPY_DETAIL_TYPE_ID_HPP
12
13 #include <boost/capy/detail/config.hpp>
14
15 #if BOOST_CAPY_NO_RTTI
16
17 //------------------------------------------------
18 // Custom implementation (no RTTI)
19 //------------------------------------------------
20
21 #include <compare>
22 #include <cstddef>
23 #include <cstdint>
24 #include <string_view>
25 #include <type_traits>
26
27 namespace boost {
28 namespace capy {
29 namespace detail {
30
31 template<typename T>
32 constexpr std::string_view
33 type_name_impl() noexcept
34 {
35 constexpr auto strlen_ce = [](char const* s) constexpr noexcept {
36 std::size_t n = 0;
37 while(s[n] != '\0')
38 ++n;
39 return n;
40 };
41
42 constexpr auto find = [](char const* s, std::size_t len, char c) constexpr noexcept {
43 for(std::size_t i = 0; i < len; ++i)
44 if(s[i] == c)
45 return i;
46 return len;
47 };
48
49 constexpr auto rfind = [](char const* s, std::size_t len, char c) constexpr noexcept {
50 for(std::size_t i = len; i > 0; --i)
51 if(s[i - 1] == c)
52 return i - 1;
53 return len;
54 };
55
56 #if defined(__clang__)
57 constexpr char const* s = __PRETTY_FUNCTION__;
58 constexpr std::size_t len = strlen_ce(s);
59 constexpr std::size_t start = find(s, len, '=') + 2;
60 constexpr std::size_t end = rfind(s, len, ']');
61 return {s + start, end - start};
62
63 #elif defined(__GNUC__)
64 constexpr char const* s = __PRETTY_FUNCTION__;
65 constexpr std::size_t len = strlen_ce(s);
66 constexpr std::size_t start = find(s, len, '=') + 2;
67 constexpr std::size_t end = rfind(s, len, ']');
68 return {s + start, end - start};
69
70 #elif defined(_MSC_VER)
71 constexpr char const* s = __FUNCSIG__;
72 constexpr std::size_t len = strlen_ce(s);
73 constexpr std::size_t start = find(s, len, '<') + 1;
74 constexpr std::size_t end = rfind(s, len, '>');
75 return {s + start, end - start};
76
77 #else
78 return "unknown";
79 #endif
80 }
81
82 template<typename T>
83 inline constexpr std::string_view type_name = type_name_impl<T>();
84
85 class type_info
86 {
87 void const* id_;
88 std::string_view name_;
89
90 constexpr explicit
91 type_info(void const* id, std::string_view name) noexcept
92 : id_(id)
93 , name_(name)
94 {
95 }
96
97 template<typename T>
98 friend struct type_id_impl;
99
100 public:
101 type_info(type_info const&) = default;
102 type_info& operator=(type_info const&) = default;
103
104 constexpr std::string_view
105 name() const noexcept
106 {
107 return name_;
108 }
109
110 constexpr bool
111 operator==(type_info const& rhs) const noexcept
112 {
113 return id_ == rhs.id_;
114 }
115
116 constexpr bool
117 operator!=(type_info const& rhs) const noexcept
118 {
119 return id_ != rhs.id_;
120 }
121
122 constexpr bool
123 before(type_info const& rhs) const noexcept
124 {
125 return id_ < rhs.id_;
126 }
127
128 std::uintptr_t
129 hash_code() const noexcept
130 {
131 return reinterpret_cast<std::uintptr_t>(id_);
132 }
133 };
134
135 template<typename T>
136 struct type_id_impl
137 {
138 inline static constexpr char tag{};
139 inline static constexpr type_info value{&tag, type_name<T>};
140 };
141
142 /// Returns type_info for type T (ignores top-level cv-qualifiers)
143 template<typename T>
144 inline constexpr type_info const&
145 type_id() noexcept
146 {
147 return type_id_impl<std::remove_cv_t<T>>::value;
148 }
149
150 class type_index
151 {
152 type_info const* info_;
153
154 public:
155 constexpr
156 type_index(type_info const& info) noexcept
157 : info_(&info)
158 {
159 }
160
161 constexpr std::string_view
162 name() const noexcept
163 {
164 return info_->name();
165 }
166
167 std::uintptr_t
168 hash_code() const noexcept
169 {
170 return reinterpret_cast<std::uintptr_t>(info_);
171 }
172
173 constexpr bool
174 operator==(type_index const& rhs) const noexcept = default;
175
176 constexpr std::strong_ordering
177 operator<=>(type_index const& rhs) const noexcept = default;
178 };
179
180 } // detail
181 } // capy
182 } // boost
183
184 template<>
185 struct std::hash<boost::capy::detail::type_index>
186 {
187 std::size_t
188 operator()(boost::capy::detail::type_index const& ti) const noexcept
189 {
190 return ti.hash_code();
191 }
192 };
193
194 #else // BOOST_CAPY_NO_RTTI
195
196 //------------------------------------------------
197 // Standard RTTI implementation
198 //------------------------------------------------
199
200 #include <typeinfo>
201 #include <typeindex>
202
203 namespace boost {
204 namespace capy {
205 namespace detail {
206
207 using type_info = std::type_info;
208 using type_index = std::type_index;
209
210 /// Returns type_info for type T
211 template<typename T>
212 inline type_info const&
213 222 type_id() noexcept
214 {
215 222 return typeid(T);
216 }
217
218 } // detail
219 } // capy
220 } // boost
221
222 #endif // BOOST_CAPY_NO_RTTI
223
224 #endif
225