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