]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_index/include/boost/type_index/stl_type_index.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_index / include / boost / type_index / stl_type_index.hpp
1 //
2 // Copyright (c) Antony Polukhin, 2013-2015.
3 //
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8
9 #ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
10 #define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
11
12 /// \file stl_type_index.hpp
13 /// \brief Contains boost::typeindex::stl_type_index class.
14 ///
15 /// boost::typeindex::stl_type_index class can be used as a drop-in replacement
16 /// for std::type_index.
17 ///
18 /// It is used in situations when RTTI is enabled or typeid() method is available.
19 /// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro
20 /// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index.
21
22 #include <boost/type_index/type_index_facade.hpp>
23
24 // MSVC is capable of calling typeid(T) even when RTTI is off
25 #if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
26 #error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
27 #endif
28
29 #include <typeinfo>
30 #include <cstring> // std::strcmp, std::strlen, std::strstr
31 #include <stdexcept>
32 #include <boost/static_assert.hpp>
33 #include <boost/throw_exception.hpp>
34 #include <boost/core/demangle.hpp>
35 #include <boost/type_traits/is_const.hpp>
36 #include <boost/type_traits/is_reference.hpp>
37 #include <boost/type_traits/is_volatile.hpp>
38 #include <boost/type_traits/remove_cv.hpp>
39 #include <boost/type_traits/remove_reference.hpp>
40 #include <boost/mpl/if.hpp>
41 #include <boost/mpl/or.hpp>
42
43 #if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
44 || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
45 # include <boost/type_traits/is_signed.hpp>
46 # include <boost/type_traits/make_signed.hpp>
47 # include <boost/mpl/identity.hpp>
48 #endif
49
50 #ifdef BOOST_HAS_PRAGMA_ONCE
51 # pragma once
52 #endif
53
54 namespace boost { namespace typeindex {
55
56 /// \class stl_type_index
57 /// This class is a wrapper around std::type_info, that workarounds issues and provides
58 /// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade.
59 ///
60 /// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index.
61 class stl_type_index
62 : public type_index_facade<
63 stl_type_index,
64 #ifdef BOOST_NO_STD_TYPEINFO
65 type_info
66 #else
67 std::type_info
68 #endif
69 >
70 {
71 public:
72 #ifdef BOOST_NO_STD_TYPEINFO
73 typedef type_info type_info_t;
74 #else
75 typedef std::type_info type_info_t;
76 #endif
77
78 private:
79 const type_info_t* data_;
80
81 public:
82 inline stl_type_index() BOOST_NOEXCEPT
83 : data_(&typeid(void))
84 {}
85
86 inline stl_type_index(const type_info_t& data) BOOST_NOEXCEPT
87 : data_(&data)
88 {}
89
90 inline const type_info_t& type_info() const BOOST_NOEXCEPT;
91
92 inline const char* raw_name() const BOOST_NOEXCEPT;
93 inline const char* name() const BOOST_NOEXCEPT;
94 inline std::string pretty_name() const;
95
96 inline std::size_t hash_code() const BOOST_NOEXCEPT;
97 inline bool equal(const stl_type_index& rhs) const BOOST_NOEXCEPT;
98 inline bool before(const stl_type_index& rhs) const BOOST_NOEXCEPT;
99
100 template <class T>
101 inline static stl_type_index type_id() BOOST_NOEXCEPT;
102
103 template <class T>
104 inline static stl_type_index type_id_with_cvr() BOOST_NOEXCEPT;
105
106 template <class T>
107 inline static stl_type_index type_id_runtime(const T& value) BOOST_NOEXCEPT;
108 };
109
110 inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT {
111 return *data_;
112 }
113
114
115 inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT {
116 #ifdef _MSC_VER
117 return data_->raw_name();
118 #else
119 return data_->name();
120 #endif
121 }
122
123 inline const char* stl_type_index::name() const BOOST_NOEXCEPT {
124 return data_->name();
125 }
126
127 inline std::string stl_type_index::pretty_name() const {
128 static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<";
129 static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1;
130
131 // In case of MSVC demangle() is a no-op, and name() already returns demangled name.
132 // In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it.
133 const boost::core::scoped_demangled_name demangled_name(data_->name());
134
135 const char* begin = demangled_name.get();
136 if (!begin) {
137 boost::throw_exception(std::runtime_error("Type name demangling failed"));
138 }
139
140 const std::string::size_type len = std::strlen(begin);
141 const char* end = begin + len;
142
143 if (len > cvr_saver_name_len) {
144 const char* b = std::strstr(begin, cvr_saver_name);
145 if (b) {
146 b += cvr_saver_name_len;
147
148 // Trim leading spaces
149 while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size
150 ++ b;
151 }
152
153 // Skip the closing angle bracket
154 const char* e = end - 1;
155 while (e > b && *e != '>') {
156 -- e;
157 }
158
159 // Trim trailing spaces
160 while (e > b && *(e - 1) == ' ') {
161 -- e;
162 }
163
164 if (b < e) {
165 // Parsing seems to have succeeded, the type name is not empty
166 begin = b;
167 end = e;
168 }
169 }
170 }
171
172 return std::string(begin, end);
173 }
174
175
176 inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT {
177 #if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
178 return data_->hash_code();
179 #else
180 return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
181 #endif
182 }
183
184
185 /// @cond
186
187 // for this compiler at least, cross-shared-library type_info
188 // comparisons don't work, so we are using typeid(x).name() instead.
189 # if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
190 || defined(_AIX) \
191 || (defined(__sgi) && defined(__host_mips)) \
192 || (defined(__hpux) && defined(__HP_aCC)) \
193 || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
194 # define BOOST_CLASSINFO_COMPARE_BY_NAMES
195 # endif
196
197 /// @endcond
198
199 inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEPT {
200 #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
201 return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
202 #else
203 return !!(*data_ == *rhs.data_);
204 #endif
205 }
206
207 inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCEPT {
208 #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
209 return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
210 #else
211 return !!data_->before(*rhs.data_);
212 #endif
213 }
214
215 #ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
216 #undef BOOST_CLASSINFO_COMPARE_BY_NAMES
217 #endif
218
219
220
221 template <class T>
222 inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT {
223 typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
224 typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_prefinal_t;
225
226 # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
227 || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
228
229 // Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral'
230 // in typeid() expressions. Full template specialization for 'integral' fixes that issue:
231 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
232 boost::is_signed<no_cvr_prefinal_t>,
233 boost::make_signed<no_cvr_prefinal_t>,
234 boost::mpl::identity<no_cvr_prefinal_t>
235 >::type no_cvr_prefinal_lazy_t;
236
237 typedef BOOST_DEDUCED_TYPENAME no_cvr_prefinal_t::type no_cvr_t;
238 #else
239 typedef no_cvr_prefinal_t no_cvr_t;
240 #endif
241
242 return typeid(no_cvr_t);
243 }
244
245 namespace detail {
246 template <class T> class cvr_saver{};
247 }
248
249 template <class T>
250 inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
251 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
252 boost::mpl::or_<boost::is_reference<T>, boost::is_const<T>, boost::is_volatile<T> >,
253 detail::cvr_saver<T>,
254 T
255 >::type type;
256
257 return typeid(type);
258 }
259
260
261 template <class T>
262 inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT {
263 #ifdef BOOST_NO_RTTI
264 return value.boost_type_index_type_id_runtime_();
265 #else
266 return typeid(value);
267 #endif
268 }
269
270 }} // namespace boost::typeindex
271
272 #endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP