Conversation
|
An automated preview of the documentation is available at https://64.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-03-01 19:36:01 UTC |
There was a problem hiding this comment.
Pull request overview
Adds interoperability between Boost.OpenMethod dispatch and std::any, enabling method calls where virtual parameters are passed as std::any (or references), using the contained runtime type to drive dispatch.
Changes:
- Introduces
boost/openmethod/interop/std_any.hppwithvirtual_traits/ registration helpers forstd::any. - Extends vptr policies with
type_vptr(type_id)to support vptr lookup directly from a type id. - Updates core dispatch (
acquire_vptr) to optionally usevirtual_traits::dynamic_vptrwhen provided, and adds a newstd::anydispatch test.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
include/boost/openmethod/interop/std_any.hpp |
New std::any interop layer (virtual traits + registration helper). |
include/boost/openmethod/core.hpp |
Adds detection/branch intended to let virtual_traits provide vptr acquisition. |
include/boost/openmethod/policies/vptr_vector.hpp |
Adds type_vptr(type_id) helper and refactors dynamic_vptr to reuse it. |
include/boost/openmethod/policies/vptr_map.hpp |
Adds type_vptr(type_id) helper and refactors dynamic_vptr to reuse it. |
include/boost/openmethod/preamble.hpp |
Adds a macro for generating “has static function” detection traits. |
test/test_dispatch_std_any.cpp |
New tests for std::any dispatch (currently with some cases compiled out). |
.gitignore |
Ignores generated doc output and Coverity directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| //! @param arg A reference to a const `any`. | ||
| //! @return A reference to a the v-table pointer for `Class`. | ||
| static auto dynamic_vptr(const std::any& arg) -> const vptr_type& { | ||
| return Registry::rtti::type_vptr(arg.type()); |
There was a problem hiding this comment.
Registry::rtti::type_vptr is called here, but the RTTI policy (Registry::rtti) does not define type_vptr (the new type_vptr helper lives on the vptr policy, e.g. Registry::vptr::type_vptr). Also arg.type() is a const std::type_info&, while this library’s type_id for std_rtti is &typeid(T) (a pointer). This currently won’t compile; convert to a type_id (e.g. &arg.type()) and route through the vptr policy’s type_vptr.
| return Registry::rtti::type_vptr(arg.type()); | |
| return Registry::vptr::type_vptr(&arg.type()); |
| template<class Registry> | ||
| struct validate_method_parameter<virtual_<const std::any&>, Registry, void> | ||
| : std::true_type {}; | ||
|
|
||
| template<class Registry> | ||
| struct validate_method_parameter<virtual_<std::any&>, Registry, void> | ||
| : std::true_type {}; |
There was a problem hiding this comment.
This header declares validate_method_parameter support for virtual_<std::any&>, but there is no corresponding virtual_traits<std::any&, Registry> specialization. As a result, methods declared with virtual_<std::any&> will still fail to compile / dispatch correctly. Either add a virtual_traits<std::any&, Registry> specialization (with cast(std::any&) so std::any_cast<T&> is possible) or drop the validate_method_parameter<virtual_<std::any&>> specialization to avoid advertising unsupported usage.
| //! Specialize virtual_traits for `std::any&` (mutable reference). | ||
| //! | ||
| //! @tparam Registry A @ref registry. | ||
| template<class Registry> | ||
| struct virtual_traits<const std::any&, Registry> { | ||
| //! The type used for dispatch. |
There was a problem hiding this comment.
The doc says this is for std::any& (mutable reference), but the actual specialization is virtual_traits<const std::any&, Registry>. Also, with a const std::any& input, std::any_cast<T&> is not permitted, so the comment about supporting mutable references is misleading. Please update the specialization/signature (if mutability is intended) or adjust the documentation to reflect const-only behavior.
| #if 0 | ||
|
|
||
| namespace BOOST_OPENMETHOD_GENSYM { | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| // pass virtual args as std::any by value | ||
|
|
||
| MAKE_CLASSES(); | ||
|
|
||
| BOOST_OPENMETHOD(name, (virtual_<std::any>), std::string); | ||
|
|
There was a problem hiding this comment.
The test cases for virtual_<std::any> (by value) and virtual_<std::any&&> are currently compiled out with #if 0. Since the PR adds/updates support for these parameter forms in interop/std_any.hpp, leaving these tests disabled means the new behavior won’t be exercised in CI. Consider enabling these tests (or removing the corresponding public support if it’s intentionally not ready).
| //! its @ref error function with a @ref missing_class value, then | ||
| //! terminates the program with @ref abort. | ||
| //! | ||
| //! @tparam Class A registered class. |
There was a problem hiding this comment.
type_vptr is not a function template, but its doc block still lists @tparam Class A registered class. (copied from dynamic_vptr). Consider removing that @tparam line to avoid confusing generated docs.
| //! @tparam Class A registered class. |
| if constexpr (has_vptr_fn<ArgType, Registry>) { | ||
| return boost_openmethod_vptr(arg, static_cast<Registry*>(nullptr)); | ||
| } else if constexpr (has_dynamic_vptr< | ||
| virtual_traits<const ArgType&, Registry>, | ||
| type_id>) { | ||
| return virtual_traits<const ArgType&, Registry>::dynamic_vptr( | ||
| arg); | ||
| } else { | ||
| return Registry::template policy<policies::vptr>::dynamic_vptr(arg); |
There was a problem hiding this comment.
has_dynamic_vptr is being instantiated with type_id, but virtual_traits<...>::dynamic_vptr (as introduced for std::any) takes the argument type (e.g. const std::any&). As written, the trait will evaluate to false even when dynamic_vptr(const ArgType&) exists, so acquire_vptr falls back to the vptr policy path and breaks custom virtual_traits-based dispatch (likely causing compilation failures for std::any). Update the detection to test dynamic_vptr(std::declval<const ArgType&>()) (or equivalent) so the virtual_traits hook is actually used.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| //! @param arg A reference to a const `any`. | ||
| //! @return A reference to a the v-table pointer for `Class`. | ||
| static auto dynamic_vptr(const std::any& arg) -> const vptr_type& { | ||
| return Registry::rtti::type_vptr(arg.type()); |
There was a problem hiding this comment.
Same issue as the std::any by-value specialization above: Registry::rtti doesn’t provide type_vptr, and arg.type() isn’t a type_id. This should dispatch via the vptr policy (Registry::vptr::type_vptr) using a type_id derived from &arg.type() (for the std_rtti type_id representation).
| return Registry::rtti::type_vptr(arg.type()); | |
| return Registry::vptr::type_vptr(&arg.type()); |
| BOOST_OPENMETHOD_OVERRIDE(name, (const int& value), std::string) { | ||
| std::ostringstream os; | ||
| os << value << " the integer"; | ||
| return os.str(); |
There was a problem hiding this comment.
This test uses std::ostringstream but doesn’t include <sstream>, which will fail to compile on standard-conforming toolchains. Add the missing header include (ideally near the other standard headers).
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| // pass virtual args as const std::any& (const ref) | ||
|
|
||
| static_assert(detail::has_dynamic_vptr< | ||
| virtual_traits<const std::any&, default_registry>, type_id>); |
There was a problem hiding this comment.
This static_assert checks for virtual_traits<const std::any&, default_registry>::dynamic_vptr(type_id), but the dynamic_vptr overload added in std_any.hpp takes const std::any&, not a type_id. With the current has_dynamic_vptr definition in core.hpp, this assertion will fail and the test won’t compile. Align the detection (and/or this assertion) with the intended dynamic_vptr(const ArgType&) signature.
| virtual_traits<const std::any&, default_registry>, type_id>); | |
| virtual_traits<const std::any&, default_registry>, const std::any&>); |
| //! @ref error function with a @ref missing_class value, then | ||
| //! terminates the program with @ref abort. | ||
| //! | ||
| //! @tparam Class A registered class. |
There was a problem hiding this comment.
type_vptr is not a function template, but its doc block includes @tparam Class A registered class.. Please drop that @tparam line (or convert type_vptr into a template if that was intended) so the documentation matches the signature.
| //! @tparam Class A registered class. |
inter-operate with 'any'