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