type_index.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. //
  2. // Copyright 2012-2024 Antony Polukhin.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_TYPE_INDEX_HPP
  8. #define BOOST_TYPE_INDEX_HPP
  9. /// \file boost/type_index.hpp
  10. /// \brief Includes minimal set of headers required to use the Boost.TypeIndex library.
  11. ///
  12. /// By inclusion of this file most optimal type index classes will be included and used
  13. /// as a boost::typeindex::type_index and boost::typeindex::type_info.
  14. #include <boost/config.hpp>
  15. #ifdef BOOST_HAS_PRAGMA_ONCE
  16. # pragma once
  17. #endif
  18. #if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
  19. # include BOOST_TYPE_INDEX_USER_TYPEINDEX
  20. # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
  21. # pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
  22. # endif
  23. #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
  24. # include <boost/type_index/stl_type_index.hpp>
  25. # if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
  26. # include <boost/type_index/detail/stl_register_class.hpp>
  27. # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
  28. # pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
  29. # endif
  30. # else
  31. # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
  32. # pragma detect_mismatch( "boost__type_index__abi", "RTTI is used")
  33. # endif
  34. # endif
  35. #else
  36. # include <boost/type_index/ctti_type_index.hpp>
  37. # include <boost/type_index/detail/ctti_register_class.hpp>
  38. # ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
  39. # pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI")
  40. # endif
  41. #endif
  42. #ifndef BOOST_TYPE_INDEX_REGISTER_CLASS
  43. #define BOOST_TYPE_INDEX_REGISTER_CLASS
  44. #endif
  45. namespace boost { namespace typeindex {
  46. #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
  47. /// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
  48. /// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to
  49. /// deduce the name of a type. If your compiler is not recognized
  50. /// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may
  51. /// define this macro by yourself.
  52. ///
  53. /// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro
  54. /// that outputs the \b whole function signature \b including \b template \b parameters.
  55. ///
  56. /// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
  57. /// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes.
  58. ///
  59. /// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
  60. /// for an information of how to tune the implementation to make a nice pretty_name() output.
  61. #define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
  62. /// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
  63. /// This is a helper macro for making correct pretty_names() with RTTI off.
  64. ///
  65. /// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to
  66. /// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a
  67. /// support for compilers, that by default are not recognized by TypeIndex library.
  68. ///
  69. /// \b Example:
  70. ///
  71. /// Imagine the situation when
  72. /// \code boost::typeindex::ctti_type_index::type_id<int>().pretty_name() \endcode
  73. /// returns the following string:
  74. /// \code "static const char *boost::detail::ctti<int>::n() [T = int]" \endcode
  75. /// and \code boost::typeindex::ctti_type_index::type_id<short>().pretty_name() \endcode returns the following:
  76. /// \code "static const char *boost::detail::ctti<short>::n() [T = short]" \endcode
  77. ///
  78. /// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on
  79. /// the type T. After first 39 characters we have a human readable type name which is duplicated at the end
  80. /// of a string. String always ends on ']', which consumes 1 character.
  81. ///
  82. /// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to
  83. /// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode
  84. /// for `boost::typeindex::ctti_type_index::type_id<int>().pretty_name()` and \code "short>::n() [T = short" \endcode
  85. /// for `boost::typeindex::ctti_type_index::type_id<short>().pretty_name()`.
  86. ///
  87. /// Now we need to take additional care of the characters that go before the last mention of our type. We'll
  88. /// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = "
  89. /// itself:
  90. ///
  91. /// \code (39, 1, true, "T = ") \endcode
  92. ///
  93. /// In case of GCC or Clang command line we need to add the following line while compiling all the sources:
  94. ///
  95. /// \code
  96. /// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")'
  97. /// \endcode
  98. /// \param begin_skip How many characters must be skipped at the beginning of the type holding string.
  99. /// Must be a compile time constant.
  100. /// \param end_skip How many characters must be skipped at the end of the type holding string.
  101. /// Must be a compile time constant.
  102. /// \param runtime_skip Do we need additional checks at runtime to cut off the more characters.
  103. /// Must be `true` or `false`.
  104. /// \param runtime_skip_until Skip all the characters before the following string (including the string itself).
  105. /// Must be a compile time array of characters.
  106. ///
  107. /// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info.
  108. #define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "")
  109. /// Depending on a compiler flags, optimal implementation of type_index will be used
  110. /// as a default boost::typeindex::type_index.
  111. ///
  112. /// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or
  113. /// user defined type_index class.
  114. ///
  115. /// \b See boost::typeindex::type_index_facade for a full description of type_index functions.
  116. typedef platform_specific type_index;
  117. #elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
  118. // Nothing to do
  119. #elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
  120. typedef boost::typeindex::stl_type_index type_index;
  121. #else
  122. typedef boost::typeindex::ctti_type_index type_index;
  123. #endif
  124. /// Depending on a compiler flags, optimal implementation of type_info will be used
  125. /// as a default boost::typeindex::type_info.
  126. ///
  127. /// Could be a std::type_info, boost::typeindex::detail::ctti_data or
  128. /// some user defined class.
  129. ///
  130. /// type_info \b is \b not copyable or default constructible. It is \b not assignable too!
  131. typedef type_index::type_info_t type_info;
  132. #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
  133. /// \def BOOST_TYPE_INDEX_USER_TYPEINDEX
  134. /// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file
  135. /// with user provided implementation of type_index.
  136. ///
  137. /// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section
  138. /// of documentation for usage example.
  139. #define BOOST_TYPE_INDEX_USER_TYPEINDEX <full/absolute/path/to/header/with/type_index.hpp>
  140. /// \def BOOST_TYPE_INDEX_REGISTER_CLASS
  141. /// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI.
  142. /// Put this macro into the public section of polymorphic class to allow runtime type detection.
  143. ///
  144. /// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function
  145. /// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`.
  146. ///
  147. /// \b Example:
  148. /// \code
  149. /// class A {
  150. /// public:
  151. /// BOOST_TYPE_INDEX_REGISTER_CLASS
  152. /// virtual ~A(){}
  153. /// };
  154. ///
  155. /// struct B: public A {
  156. /// BOOST_TYPE_INDEX_REGISTER_CLASS
  157. /// };
  158. ///
  159. /// struct C: public B {
  160. /// BOOST_TYPE_INDEX_REGISTER_CLASS
  161. /// };
  162. ///
  163. /// ...
  164. ///
  165. /// C c1;
  166. /// A* pc1 = &c1;
  167. /// assert(boost::typeindex::type_id<C>() == boost::typeindex::type_id_runtime(*pc1));
  168. /// \endcode
  169. #define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions
  170. /// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
  171. /// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing
  172. /// RTTI on/off modules. See
  173. /// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html)
  174. /// section of documentation for more info.
  175. #define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
  176. #endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
  177. /// Function to get boost::typeindex::type_index for a type T.
  178. /// Removes const, volatile && and & modifiers from T.
  179. ///
  180. /// \b Example:
  181. /// \code
  182. /// type_index ti = type_id<int&>();
  183. /// std::cout << ti.pretty_name(); // Outputs 'int'
  184. /// \endcode
  185. ///
  186. /// \tparam T Type for which type_index must be created.
  187. /// \throw Nothing.
  188. /// \return boost::typeindex::type_index with information about the specified type T.
  189. template <class T>
  190. inline type_index type_id() noexcept {
  191. return type_index::type_id<T>();
  192. }
  193. /// Function for constructing boost::typeindex::type_index instance for type T.
  194. /// Does not remove const, volatile, & and && modifiers from T.
  195. ///
  196. /// If T has no const, volatile, & and && modifiers, then returns exactly
  197. /// the same result as in case of calling `type_id<T>()`.
  198. ///
  199. /// \b Example:
  200. /// \code
  201. /// type_index ti = type_id_with_cvr<int&>();
  202. /// std::cout << ti.pretty_name(); // Outputs 'int&'
  203. /// \endcode
  204. ///
  205. /// \tparam T Type for which type_index must be created.
  206. /// \throw Nothing.
  207. /// \return boost::typeindex::type_index with information about the specified type T.
  208. template <class T>
  209. inline type_index type_id_with_cvr() noexcept {
  210. return type_index::type_id_with_cvr<T>();
  211. }
  212. /// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
  213. ///
  214. /// Returns runtime information about specified type.
  215. ///
  216. /// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS.
  217. ///
  218. /// \b Example:
  219. /// \code
  220. /// struct Base { virtual ~Base(){} };
  221. /// struct Derived: public Base {};
  222. /// ...
  223. /// Derived d;
  224. /// Base& b = d;
  225. /// type_index ti = type_id_runtime(b);
  226. /// std::cout << ti.pretty_name(); // Outputs 'Derived'
  227. /// \endcode
  228. ///
  229. /// \param runtime_val Variable which runtime type must be returned.
  230. /// \throw Nothing.
  231. /// \return boost::typeindex::type_index with information about the specified variable.
  232. template <class T>
  233. inline type_index type_id_runtime(const T& runtime_val) noexcept {
  234. return type_index::type_id_runtime(runtime_val);
  235. }
  236. }} // namespace boost::typeindex
  237. #endif // BOOST_TYPE_INDEX_HPP