Line data 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
|