
AMDG On 5/8/25 8:13 PM, Jean-Louis Leroy via Boost wrote:
343: if (*method.vp_end == 0) { Since this is inside the loop, won't it only resolve the first type? Actually, I'm really confused about the whole loop. Do we want to process the overriders for each virtual parameter?
That code has nothing to do with resolving overriders. It is for deferred RTTI. For interfacing with custom RTTI schemes that also use static ctors. If the deferred_static_rtti is present, I store a pointer to a function that returns a type_id, instead of the type_id itself. initialize() calls the function and then replaces the function pointer with the type_id. Since initialize() can be called multiple times, I add a flag just after method.vp_end.
For reference here's the code in question: for (auto& method : Policy::methods) { for (auto& ti : range{method.vp_begin, method.vp_end}) { if (*method.vp_end == 0) { resolve(&ti); *method.vp_end = 1; } for (auto& overrider : method.specs) { if (*overrider.vp_end == 0) { for (auto& ti : range{overrider.vp_begin, overrider.vp_end}) { resolve(&ti); } *overrider.vp_end = 1; } } } } There are four nested loops. The outer and innermost loops look sane to me. The two middle loops do not. The second loop is iterating over the parameter types of the base method and resolving them. However, because it sets *method.vp_end = 1 on the first iteration, only the type of the first parameter will be resolved. I think this will fail for multimethods (See below for a program that fails). The third loop, I think should be directly inside the outer loop, instead of being nested inside the second, but it looks harmless because *overrider.vp_end == 0 will deduplicate. #include <boost/openmethod.hpp> #include <boost/openmethod/compiler.hpp> #include <boost/openmethod/policies.hpp> namespace bom = boost::openmethod; struct B { virtual ~B() = default; bom::type_id type = static_type; static bom::type_id static_type; }; struct D : B { D() { type = static_type; } static bom::type_id static_type; }; bom::type_id B::static_type; bom::type_id D::static_type; struct deferred_rtti : bom::policies::deferred_static_rtti { template <class T> static constexpr bool is_polymorphic = std::is_base_of_v<B, T>; template <typename T> static auto static_type() -> bom::type_id { if constexpr (is_polymorphic<T>) { return T::static_type; } else { return 0; } } template <typename T> static auto dynamic_type(const T &obj) -> bom::type_id { if constexpr (is_polymorphic<T>) { return obj.type; } else { return 0; } } }; struct deferred_rtti_policy : boost::openmethod::policies::debug::fork<deferred_rtti_policy>::replace< boost::openmethod::policies::rtti, deferred_rtti> {}; BOOST_OPENMETHOD_CLASSES(B, D, deferred_rtti_policy) BOOST_OPENMETHOD(foo, (virtual_ptr<B, deferred_rtti_policy>, virtual_ptr<B, deferred_rtti_policy>), void, deferred_rtti_policy); BOOST_OPENMETHOD_OVERRIDE(foo, (virtual_ptr<D, deferred_rtti_policy>, virtual_ptr<D, deferred_rtti_policy>), void) {} int main() { B::static_type = 23; D::static_type = 4; bom::initialize<deferred_rtti_policy>(); D d; B &b(d); foo(b, b); } $ BOOST_OPENMETHOD_TRACE=1 ./a.out Static class info: type_id(4): (type_id(23), type_id(4)) type_id(23): (type_id(23)) Inheritance lattice: type_id(4) bases: (type_id(23)) derived: () covariant: (type_id(4)) type_id(23) bases: () derived: (type_id(4)) covariant: (type_id(4), type_id(23)) Methods: type_id(0) (type_id(23), type_id(4227983)) unkown class 4227983(type_id(4227983)) for parameter #1 unknown class type_id(4227983) Aborted (core dumped) In Christ, Steven Watanabe