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