type_index_facade.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. #ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
  9. #define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
  10. #include <boost/config.hpp>
  11. #include <boost/container_hash/hash_fwd.hpp>
  12. #include <string>
  13. #include <cstring>
  14. #if !defined(BOOST_NO_IOSTREAM)
  15. #if !defined(BOOST_NO_IOSFWD)
  16. #include <iosfwd> // for std::basic_ostream
  17. #else
  18. #include <ostream>
  19. #endif
  20. #endif
  21. #ifdef BOOST_HAS_PRAGMA_ONCE
  22. # pragma once
  23. #endif
  24. namespace boost { namespace typeindex {
  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.
  55. template <class Derived, class TypeInfo>
  56. class type_index_facade {
  57. private:
  58. /// @cond
  59. BOOST_CXX14_CONSTEXPR const Derived & derived() const BOOST_NOEXCEPT {
  60. return *static_cast<Derived const*>(this);
  61. }
  62. /// @endcond
  63. public:
  64. typedef TypeInfo type_info_t;
  65. /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
  66. /// \return Name of a type. By default returns Derived::raw_name().
  67. inline const char* name() const BOOST_NOEXCEPT {
  68. return derived().raw_name();
  69. }
  70. /// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
  71. /// \return Human readable type name. By default returns Derived::name().
  72. inline std::string pretty_name() const {
  73. return derived().name();
  74. }
  75. /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
  76. /// \return True if two types are equal. By default compares types by raw_name().
  77. inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT {
  78. const char* const left = derived().raw_name();
  79. const char* const right = rhs.raw_name();
  80. return left == right || !std::strcmp(left, right);
  81. }
  82. /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
  83. /// \return True if rhs is greater than this. By default compares types by raw_name().
  84. inline bool before(const Derived& rhs) const BOOST_NOEXCEPT {
  85. const char* const left = derived().raw_name();
  86. const char* const right = rhs.raw_name();
  87. return left != right && std::strcmp(left, right) < 0;
  88. }
  89. /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
  90. /// \return Hash code of a type. By default hashes types by raw_name().
  91. /// \note Derived class header \b must include <boost/container_hash/hash.hpp>, \b unless this function is redefined in
  92. /// Derived class to not use boost::hash_range().
  93. inline std::size_t hash_code() const BOOST_NOEXCEPT {
  94. const char* const name_raw = derived().raw_name();
  95. return boost::hash_range(name_raw, name_raw + std::strlen(name_raw));
  96. }
  97. #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
  98. protected:
  99. /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw.
  100. /// \return Pointer to unredable/raw type name.
  101. inline const char* raw_name() const BOOST_NOEXCEPT;
  102. /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
  103. /// \return Const reference to underlying low level type_info_t.
  104. inline const type_info_t& type_info() const BOOST_NOEXCEPT;
  105. /// This is a factory method that is used to create instances of Derived classes.
  106. /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index.
  107. ///
  108. /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
  109. /// Overrides \b must remove const, volatile && and & modifiers from T.
  110. /// \tparam T Type for which type_index must be created.
  111. /// \return type_index for type T.
  112. template <class T>
  113. static Derived type_id() BOOST_NOEXCEPT;
  114. /// This is a factory method that is used to create instances of Derived classes.
  115. /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index.
  116. ///
  117. /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
  118. /// Overrides \b must \b not remove const, volatile && and & modifiers from T.
  119. /// \tparam T Type for which type_index must be created.
  120. /// \return type_index for type T.
  121. template <class T>
  122. static Derived type_id_with_cvr() BOOST_NOEXCEPT;
  123. /// This is a factory method that is used to create instances of Derived classes.
  124. /// boost::typeindex::type_id_runtime(const T&) 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.
  127. /// \param variable Variable which runtime type will be stored in type_index.
  128. /// \return type_index with runtime type of variable.
  129. template <class T>
  130. static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT;
  131. #endif
  132. };
  133. /// @cond
  134. template <class Derived, class TypeInfo>
  135. BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  136. return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs));
  137. }
  138. template <class Derived, class TypeInfo>
  139. BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  140. return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));
  141. }
  142. template <class Derived, class TypeInfo>
  143. BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  144. return rhs < lhs;
  145. }
  146. template <class Derived, class TypeInfo>
  147. BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  148. return !(lhs > rhs);
  149. }
  150. template <class Derived, class TypeInfo>
  151. BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  152. return !(lhs < rhs);
  153. }
  154. template <class Derived, class TypeInfo>
  155. BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  156. return !(lhs == rhs);
  157. }
  158. // ######################### COMPARISONS with Derived ############################ //
  159. template <class Derived, class TypeInfo>
  160. inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  161. return Derived(lhs) == rhs;
  162. }
  163. template <class Derived, class TypeInfo>
  164. inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  165. return Derived(lhs) < rhs;
  166. }
  167. template <class Derived, class TypeInfo>
  168. inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  169. return rhs < Derived(lhs);
  170. }
  171. template <class Derived, class TypeInfo>
  172. inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  173. return !(Derived(lhs) > rhs);
  174. }
  175. template <class Derived, class TypeInfo>
  176. inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  177. return !(Derived(lhs) < rhs);
  178. }
  179. template <class Derived, class TypeInfo>
  180. inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
  181. return !(Derived(lhs) == rhs);
  182. }
  183. template <class Derived, class TypeInfo>
  184. inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  185. return lhs == Derived(rhs);
  186. }
  187. template <class Derived, class TypeInfo>
  188. inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  189. return lhs < Derived(rhs);
  190. }
  191. template <class Derived, class TypeInfo>
  192. inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  193. return Derived(rhs) < lhs;
  194. }
  195. template <class Derived, class TypeInfo>
  196. inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  197. return !(lhs > Derived(rhs));
  198. }
  199. template <class Derived, class TypeInfo>
  200. inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  201. return !(lhs < Derived(rhs));
  202. }
  203. template <class Derived, class TypeInfo>
  204. inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
  205. return !(lhs == Derived(rhs));
  206. }
  207. // ######################### COMPARISONS with Derived END ############################ //
  208. /// @endcond
  209. #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
  210. /// noexcept comparison operators for type_index_facade classes.
  211. bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
  212. /// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
  213. bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
  214. /// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
  215. bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
  216. #endif
  217. #ifndef BOOST_NO_IOSTREAM
  218. #ifdef BOOST_NO_TEMPLATED_IOSTREAMS
  219. /// @cond
  220. /// Ostream operator that will output demangled name
  221. template <class Derived, class TypeInfo>
  222. inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) {
  223. ostr << static_cast<Derived const&>(ind).pretty_name();
  224. return ostr;
  225. }
  226. /// @endcond
  227. #else
  228. /// Ostream operator that will output demangled name.
  229. template <class CharT, class TriatT, class Derived, class TypeInfo>
  230. inline std::basic_ostream<CharT, TriatT>& operator<<(
  231. std::basic_ostream<CharT, TriatT>& ostr,
  232. const type_index_facade<Derived, TypeInfo>& ind)
  233. {
  234. ostr << static_cast<Derived const&>(ind).pretty_name();
  235. return ostr;
  236. }
  237. #endif // BOOST_NO_TEMPLATED_IOSTREAMS
  238. #endif // BOOST_NO_IOSTREAM
  239. /// This free function is used by Boost's unordered containers.
  240. /// \note <boost/container_hash/hash.hpp> has to be included if this function is used.
  241. template <class Derived, class TypeInfo>
  242. inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT {
  243. return static_cast<Derived const&>(lhs).hash_code();
  244. }
  245. }} // namespace boost::typeindex
  246. #endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP