std_rtti.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (c) 2018-2025 Jean-Louis Leroy
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_OPENMETHOD_POLICY_STD_RTTI_HPP
  6. #define BOOST_OPENMETHOD_POLICY_STD_RTTI_HPP
  7. #include <boost/openmethod/preamble.hpp>
  8. #ifndef BOOST_NO_RTTI
  9. #include <typeindex>
  10. #include <typeinfo>
  11. #include <boost/core/demangle.hpp>
  12. #endif
  13. namespace boost::openmethod::policies {
  14. //! Implements the @ref rtti policy using standard RTTI.
  15. //!
  16. //! `std_rtti` implements the `rtti` policy using the standard C++ RTTI system.
  17. //! It is the default RTTI policy.
  18. struct std_rtti : rtti {
  19. //! A RttiFn metafunction.
  20. //!
  21. //! @tparam Registry The registry containing this policy.
  22. template<class Registry>
  23. struct fn {
  24. #ifndef BOOST_NO_RTTI
  25. //! Tests if a class is polymorphic.
  26. //!
  27. //! Evaluates to `true` if `Class` is a polymorphic class, as defined by
  28. //! the C++ standard, i.e. a class that contains at least one virtual
  29. //! function.
  30. //!
  31. //! @tparam Class A class.
  32. template<class Class>
  33. static constexpr bool is_polymorphic = std::is_polymorphic_v<Class>;
  34. //! Returns the static @ref type_id of a type.
  35. //!
  36. //! Returns `&typeid(Class)`, cast to `type_id`.
  37. //!
  38. //! @tparam Class A class.
  39. //! @return The static type_id of Class.
  40. template<class Class>
  41. static auto static_type() -> type_id {
  42. return &typeid(Class);
  43. }
  44. //! Returns the dynamic @ref type_id of an object.
  45. //!
  46. //! Returns `&typeid(obj)`, cast to `type_id`.
  47. //!
  48. //! @tparam Class A registered class.
  49. //! @param obj A reference to an instance of `Class`.
  50. //! @return The type_id of `obj`'s class.
  51. template<class Class>
  52. static auto dynamic_type(const Class& obj) -> type_id {
  53. return &typeid(obj);
  54. }
  55. //! Writes a representation of a @ref type_id to a stream.
  56. //!
  57. //! Writes the demangled name of the class identified by `type` to
  58. //! `stream`.
  59. //!
  60. //! @tparam Stream A SimpleOutputStream.
  61. //! @param type The `type_id` to write.
  62. //! @param stream The stream to write to.
  63. template<typename Stream>
  64. static auto type_name(type_id type, Stream& stream) -> void {
  65. stream << boost::core::demangle(
  66. reinterpret_cast<const std::type_info*>(type)->name());
  67. }
  68. //! Returns a key that uniquely identifies a class.
  69. //!
  70. //! C++ does *not* guarantee that there is a single instance of
  71. //! `std::type_info` per type. `std_rtti` uses the addresses of
  72. //! `std::type_index` objects as `type_id`s. Thus, the same class may
  73. //! have multiple corresponding `type_id`s. `std::type_index` objects,
  74. //! on the other hand, are guaranteed to compare as equal iff they
  75. //! correspond to the same class, and they can be used to identify the
  76. //! `type_id`s pertaining to the same class.
  77. //!
  78. //! @param type A `type_id`.
  79. //! @return A `std::type_index` for `type` (cast to a `const std::type_info&`).
  80. static auto type_index(type_id type) -> std::type_index {
  81. return std::type_index(
  82. *reinterpret_cast<const std::type_info*>(type));
  83. }
  84. //! Casts an object to a type.
  85. //!
  86. //! Casts `obj` to a reference to an instance of `D`, using
  87. //! `dynamic_cast`.
  88. //!
  89. //! @tparam D A reference to a subclass of `B`.
  90. //! @tparam B A registered class.
  91. //! @param obj A reference to an instance of `B`.
  92. template<typename D, typename B>
  93. static auto dynamic_cast_ref(B&& obj) -> D {
  94. return dynamic_cast<D>(obj);
  95. }
  96. #endif
  97. };
  98. };
  99. } // namespace boost::openmethod::policies
  100. #endif