1//
2// Copyright 2013-2024 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_TYPE_INDEX_FACADE_HPP
10#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
11
12#include <boost/config.hpp>
13#include <boost/container_hash/hash_fwd.hpp>
14#include <string>
15#include <cstring>
16#include <type_traits>
17#include <iosfwd> // for std::basic_ostream
18
19#ifdef BOOST_HAS_PRAGMA_ONCE
20# pragma once
21#endif
22
23namespace boost { namespace typeindex {
24
25/// \class type_index_facade
26///
27/// This class takes care about the comparison operators, hash functions and
28/// ostream operators. Use this class as a public base class for defining new
29/// type_info-conforming classes.
30///
31/// \b Example:
32/// \code
33/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info>
34/// {
35/// public:
36/// typedef std::type_info type_info_t;
37/// private:
38/// const type_info_t* data_;
39///
40/// public:
41/// stl_type_index(const type_info_t& data) noexcept
42/// : data_(&data)
43/// {}
44/// // ...
45/// };
46/// \endcode
47///
48/// \tparam Derived Class derived from type_index_facade.
49/// \tparam TypeInfo Class that will be used as a base type_info class.
50/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade.
51/// Protected member functions raw_name() \b must be defined in Derived class. All the other
52/// methods are mandatory.
53/// \see 'Making a custom type_index' section for more information about
54/// creating your own type_index using type_index_facade.
55template <class Derived, class TypeInfo>
56class type_index_facade {
57private:
58 /// @cond
59 BOOST_CXX14_CONSTEXPR const Derived & derived() const noexcept {
60 return *static_cast<Derived const*>(this);
61 }
62 /// @endcond
63public:
64 typedef TypeInfo type_info_t;
65
66 /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
67 /// \return Name of a type. By default returns Derived::raw_name().
68 inline const char* name() const noexcept {
69 return derived().raw_name();
70 }
71
72 /// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
73 /// \return Human readable type name. By default returns Derived::name().
74 inline std::string pretty_name() const {
75 return derived().name();
76 }
77
78 /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
79 /// \return True if two types are equal. By default compares types by raw_name().
80 inline bool equal(const Derived& rhs) const noexcept {
81 const char* const left = derived().raw_name();
82 const char* const right = rhs.raw_name();
83 return left == right || !std::strcmp(s1: left, s2: right);
84 }
85
86 /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
87 /// \return True if rhs is greater than this. By default compares types by raw_name().
88 inline bool before(const Derived& rhs) const noexcept {
89 const char* const left = derived().raw_name();
90 const char* const right = rhs.raw_name();
91 return left != right && std::strcmp(s1: left, s2: right) < 0;
92 }
93
94 /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
95 /// \return Hash code of a type. By default hashes types by raw_name().
96 /// \note Derived class header \b must include <boost/container_hash/hash.hpp>, \b unless this function is redefined in
97 /// Derived class to not use boost::hash_range().
98 inline std::size_t hash_code() const noexcept {
99 const char* const name_raw = derived().raw_name();
100 return boost::hash_range(name_raw, name_raw + std::strlen(s: name_raw));
101 }
102
103#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
104protected:
105 /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw.
106 /// \return Pointer to unredable/raw type name.
107 inline const char* raw_name() const noexcept;
108
109 /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
110 /// \return Const reference to underlying low level type_info_t.
111 inline const type_info_t& type_info() const noexcept;
112
113 /// This is a factory method that is used to create instances of Derived classes.
114 /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index.
115 ///
116 /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
117 /// Overrides \b must remove const, volatile && and & modifiers from T.
118 /// \tparam T Type for which type_index must be created.
119 /// \return type_index for type T.
120 template <class T>
121 static Derived type_id() noexcept;
122
123 /// This is a factory method that is used to create instances of Derived classes.
124 /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index.
125 ///
126 /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
127 /// Overrides \b must \b not remove const, volatile && and & modifiers from T.
128 /// \tparam T Type for which type_index must be created.
129 /// \return type_index for type T.
130 template <class T>
131 static Derived type_id_with_cvr() noexcept;
132
133 /// This is a factory method that is used to create instances of Derived classes.
134 /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index.
135 ///
136 /// \b Override: This function \b may be redefined and made public in Derived class.
137 /// \param variable Variable which runtime type will be stored in type_index.
138 /// \return type_index with runtime type of variable.
139 template <class T>
140 static Derived type_id_runtime(const T& variable) noexcept;
141
142#endif
143
144};
145
146/// @cond
147template <class Derived, class TypeInfo>
148BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
149 return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs));
150}
151
152template <class Derived, class TypeInfo>
153BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
154 return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));
155}
156
157
158
159template <class Derived, class TypeInfo>
160BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
161 return rhs < lhs;
162}
163
164template <class Derived, class TypeInfo>
165BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
166 return !(lhs > rhs);
167}
168
169template <class Derived, class TypeInfo>
170BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
171 return !(lhs < rhs);
172}
173
174template <class Derived, class TypeInfo>
175BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
176 return !(lhs == rhs);
177}
178
179// ######################### COMPARISONS with Derived ############################ //
180template <class Derived, class TypeInfo>
181inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
182 return Derived(lhs) == rhs;
183}
184
185template <class Derived, class TypeInfo>
186inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
187 return Derived(lhs) < rhs;
188}
189
190template <class Derived, class TypeInfo>
191inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
192 return rhs < Derived(lhs);
193}
194
195template <class Derived, class TypeInfo>
196inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
197 return !(Derived(lhs) > rhs);
198}
199
200template <class Derived, class TypeInfo>
201inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
202 return !(Derived(lhs) < rhs);
203}
204
205template <class Derived, class TypeInfo>
206inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) noexcept {
207 return !(Derived(lhs) == rhs);
208}
209
210
211template <class Derived, class TypeInfo>
212inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
213 return lhs == Derived(rhs);
214}
215
216template <class Derived, class TypeInfo>
217inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
218 return lhs < Derived(rhs);
219}
220
221template <class Derived, class TypeInfo>
222inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
223 return Derived(rhs) < lhs;
224}
225
226template <class Derived, class TypeInfo>
227inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
228 return !(lhs > Derived(rhs));
229}
230
231template <class Derived, class TypeInfo>
232inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
233 return !(lhs < Derived(rhs));
234}
235
236template <class Derived, class TypeInfo>
237inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) noexcept {
238 return !(lhs == Derived(rhs));
239}
240
241// ######################### COMPARISONS with Derived END ############################ //
242
243/// @endcond
244
245#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
246
247/// noexcept comparison operators for type_index_facade classes.
248bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
249
250/// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
251bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
252
253/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
254bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
255
256#endif
257
258#ifndef BOOST_NO_IOSTREAM
259/// Ostream operator that will output demangled name.
260template <class CharT, class TriatT, class Derived, class TypeInfo>
261inline std::basic_ostream<CharT, TriatT>& operator<<(
262 std::basic_ostream<CharT, TriatT>& ostr,
263 const type_index_facade<Derived, TypeInfo>& ind)
264{
265 ostr << static_cast<Derived const&>(ind).pretty_name();
266 return ostr;
267}
268#endif // BOOST_NO_IOSTREAM
269
270/// This free function is used by Boost's unordered containers.
271/// \note <boost/container_hash/hash.hpp> has to be included if this function is used.
272template <class Derived, class TypeInfo>
273inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) noexcept {
274 return static_cast<Derived const&>(lhs).hash_code();
275}
276
277}} // namespace boost::typeindex
278
279#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
280
281

source code of boost/libs/type_index/include/boost/type_index/type_index_facade.hpp