vptr_map.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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_VPTR_MAP_HPP
  6. #define BOOST_OPENMETHOD_POLICY_VPTR_MAP_HPP
  7. #include <boost/openmethod/preamble.hpp>
  8. #include <unordered_map>
  9. namespace boost::openmethod {
  10. namespace policies {
  11. //! Stores v-table pointers in a map keyed by `type_id`s.
  12. //!
  13. //! `vptr_map` stores v-table pointers in a map keyed by `type_id`s.
  14. //!
  15. //! If the registry contains the @ref indirect_vptr policy, `vptr_map` stores
  16. //! pointers to pointers to v-tables.
  17. //!
  18. //! @tparam MapFn A mp11 quoted metafunction that takes a key type and a
  19. //! value type, and returns an @ref AssociativeContainer.
  20. template<class MapFn = mp11::mp_quote<std::unordered_map>>
  21. class vptr_map : public vptr {
  22. public:
  23. //! A VptrFn metafunction.
  24. //!
  25. //! @tparam Registry The registry containing this policy.
  26. template<class Registry>
  27. class fn {
  28. using Value = std::conditional_t<
  29. Registry::has_indirect_vptr, const vptr_type*, vptr_type>;
  30. static inline typename MapFn::template fn<type_id, Value> vptrs;
  31. public:
  32. //! Stores the v-table pointers.
  33. //!
  34. //! @tparam Context An @ref InitializeContext.
  35. //! @tparam Options... Zero or more option types.
  36. //! @param ctx A Context object.
  37. //! @param options A tuple of option objects.
  38. template<class Context, class... Options>
  39. static void
  40. initialize(const Context& ctx, const std::tuple<Options...>&) {
  41. decltype(vptrs) new_vptrs;
  42. for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
  43. ++iter) {
  44. for (auto type_iter = iter->type_id_begin();
  45. type_iter != iter->type_id_end(); ++type_iter) {
  46. if constexpr (Registry::has_indirect_vptr) {
  47. new_vptrs.emplace(*type_iter, &iter->vptr());
  48. } else {
  49. new_vptrs.emplace(*type_iter, iter->vptr());
  50. }
  51. }
  52. }
  53. vptrs.swap(new_vptrs);
  54. }
  55. //! Returns a reference to a v-table pointer for an object.
  56. //!
  57. //! Acquires the dynamic @ref type_id of `arg`, using the registry's
  58. //! @ref rtti policy.
  59. //!
  60. //! If the registry contains the @ref runtime_checks policy, checks that
  61. //! the map contains the type id. If it does not, and if the registry
  62. //! contains a @ref error_handler policy, calls its
  63. //! @ref error function with a @ref missing_class value, then
  64. //! terminates the program with @ref abort.
  65. //!
  66. //! @tparam Class A registered class.
  67. //! @param arg A reference to a const object of type `Class`.
  68. //! @return A reference to a the v-table pointer for `Class`.
  69. template<class Class>
  70. static auto dynamic_vptr(const Class& arg) -> const vptr_type& {
  71. auto type = Registry::rtti::dynamic_type(arg);
  72. auto iter = vptrs.find(type);
  73. if constexpr (Registry::has_runtime_checks) {
  74. if (iter == vptrs.end()) {
  75. if constexpr (Registry::has_error_handler) {
  76. missing_class error;
  77. error.type = type;
  78. Registry::error_handler::error(error);
  79. }
  80. abort();
  81. }
  82. }
  83. if constexpr (Registry::has_indirect_vptr) {
  84. // check for valid iterator is done if runtime_checks is enabled
  85. // coverity[deref_iterator:SUPPRESS]
  86. return *iter->second;
  87. } else {
  88. // coverity[deref_iterator:SUPPRESS]
  89. return iter->second;
  90. }
  91. }
  92. //! Clears the map.
  93. //!
  94. //! @tparam Options... Zero or more option types.
  95. //! @param ctx A Context object.
  96. //! @param options A tuple of option objects.
  97. template<class... Options>
  98. static auto finalize(const std::tuple<Options...>&) -> void {
  99. vptrs.clear();
  100. }
  101. };
  102. };
  103. } // namespace policies
  104. } // namespace boost::openmethod
  105. #endif