Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:52:04

0001 // Copyright (c) 2018-2025 Jean-Louis Leroy
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // See accompanying file LICENSE_1_0.txt
0004 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_OPENMETHOD_POLICY_VPTR_MAP_HPP
0007 #define BOOST_OPENMETHOD_POLICY_VPTR_MAP_HPP
0008 
0009 #include <boost/openmethod/preamble.hpp>
0010 
0011 #include <unordered_map>
0012 
0013 namespace boost::openmethod {
0014 
0015 namespace policies {
0016 
0017 //! Stores v-table pointers in a map keyed by `type_id`s.
0018 //!
0019 //! `vptr_map` stores v-table pointers in a map keyed by `type_id`s.
0020 //!
0021 //! If the registry contains the @ref indirect_vptr policy, `vptr_map` stores
0022 //! pointers to pointers to v-tables.
0023 //!
0024 //! @tparam MapFn A mp11 quoted metafunction that takes a key type and a
0025 //! value type, and returns an @ref AssociativeContainer.
0026 template<class MapFn = mp11::mp_quote<std::unordered_map>>
0027 class vptr_map : public vptr {
0028   public:
0029     //! A VptrFn metafunction.
0030     //!
0031     //! @tparam Registry The registry containing this policy.
0032     template<class Registry>
0033     class fn {
0034         using Value = std::conditional_t<
0035             Registry::has_indirect_vptr, const vptr_type*, vptr_type>;
0036         static inline typename MapFn::template fn<type_id, Value> vptrs;
0037 
0038       public:
0039         //! Stores the v-table pointers.
0040         //!
0041         //! @tparam Context An @ref InitializeContext.
0042         //! @tparam Options... Zero or more option types.
0043         //! @param ctx A Context object.
0044         //! @param options A tuple of option objects.
0045         template<class Context, class... Options>
0046         static void
0047         initialize(const Context& ctx, const std::tuple<Options...>&) {
0048             decltype(vptrs) new_vptrs;
0049 
0050             for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
0051                  ++iter) {
0052                 for (auto type_iter = iter->type_id_begin();
0053                      type_iter != iter->type_id_end(); ++type_iter) {
0054 
0055                     if constexpr (Registry::has_indirect_vptr) {
0056                         new_vptrs.emplace(*type_iter, &iter->vptr());
0057                     } else {
0058                         new_vptrs.emplace(*type_iter, iter->vptr());
0059                     }
0060                 }
0061             }
0062 
0063             vptrs.swap(new_vptrs);
0064         }
0065 
0066         //! Returns a reference to a v-table pointer for an object.
0067         //!
0068         //! Acquires the dynamic @ref type_id of `arg`, using the registry's
0069         //! @ref rtti policy.
0070         //!
0071         //! If the registry contains the @ref runtime_checks policy, checks that
0072         //! the map contains the type id. If it does not, and if the registry
0073         //! contains a @ref error_handler policy, calls its
0074         //! @ref error function with a @ref missing_class value, then
0075         //! terminates the program with @ref abort.
0076         //!
0077         //! @tparam Class A registered class.
0078         //! @param arg A reference to a const object of type `Class`.
0079         //! @return A reference to a the v-table pointer for `Class`.
0080         template<class Class>
0081         static auto dynamic_vptr(const Class& arg) -> const vptr_type& {
0082             auto type = Registry::rtti::dynamic_type(arg);
0083             auto iter = vptrs.find(type);
0084 
0085             if constexpr (Registry::has_runtime_checks) {
0086                 if (iter == vptrs.end()) {
0087                     if constexpr (Registry::has_error_handler) {
0088                         missing_class error;
0089                         error.type = type;
0090                         Registry::error_handler::error(error);
0091                     }
0092 
0093                     abort();
0094                 }
0095             }
0096 
0097             if constexpr (Registry::has_indirect_vptr) {
0098                 // check for valid iterator is done if runtime_checks is enabled
0099                 // coverity[deref_iterator:SUPPRESS]
0100                 return *iter->second;
0101             } else {
0102                 // coverity[deref_iterator:SUPPRESS]
0103                 return iter->second;
0104             }
0105         }
0106 
0107         //! Clears the map.
0108         //!
0109         //! @tparam Options... Zero or more option types.
0110         //! @param ctx A Context object.
0111         //! @param options A tuple of option objects.
0112         template<class... Options>
0113         static auto finalize(const std::tuple<Options...>&) -> void {
0114             vptrs.clear();
0115         }
0116     };
0117 };
0118 
0119 } // namespace policies
0120 } // namespace boost::openmethod
0121 
0122 #endif