diff --git a/examples/virtual_.cpp b/examples/virtual_.cpp index 0ec57ea..b648dd9 100644 --- a/examples/virtual_.cpp +++ b/examples/virtual_.cpp @@ -41,7 +41,7 @@ namespace virtual_intrusive { class Animal { protected: boost::openmethod::vptr_type vptr; - friend auto boost_openmethod_vptr(const Animal& a) { + friend auto boost_openmethod_vptr(const Animal& a, void*) { return a.vptr; } diff --git a/include/boost/openmethod/core.hpp b/include/boost/openmethod/core.hpp index a2dea16..ce6affe 100644 --- a/include/boost/openmethod/core.hpp +++ b/include/boost/openmethod/core.hpp @@ -301,16 +301,18 @@ constexpr bool is_virtual_ptr = detail::is_virtual_ptr_aux::value; void boost_openmethod_vptr(...); -template +template constexpr bool has_vptr_fn = std::is_same_v< - decltype(boost_openmethod_vptr(std::declval())), vptr_type>; + decltype(boost_openmethod_vptr( + std::declval(), std::declval())), + vptr_type>; template decltype(auto) acquire_vptr(const ArgType& arg) { Registry::check_initialized(); - if constexpr (detail::has_vptr_fn) { - return boost_openmethod_vptr(arg); + if constexpr (detail::has_vptr_fn) { + return boost_openmethod_vptr(arg, static_cast(nullptr)); } else { return Registry::template policy::dynamic_vptr(arg); } diff --git a/include/boost/openmethod/default_registry.hpp b/include/boost/openmethod/default_registry.hpp index 83ccc2b..0c17286 100644 --- a/include/boost/openmethod/default_registry.hpp +++ b/include/boost/openmethod/default_registry.hpp @@ -15,23 +15,23 @@ namespace boost::openmethod { -namespace policies { - -struct release : registry< - std_rtti, fast_perfect_hash, vptr_vector, - default_error_handler, stderr_output> {}; - -struct debug +struct release_registry : registry< - std_rtti, fast_perfect_hash, vptr_vector, default_error_handler, - runtime_checks, stderr_output, trace> {}; + policies::std_rtti, policies::fast_perfect_hash, + policies::vptr_vector, policies::default_error_handler, + policies::stderr_output> {}; -} // namespace policies +struct debug_registry + : registry< + policies::std_rtti, policies::fast_perfect_hash, + policies::vptr_vector, policies::default_error_handler, + policies::runtime_checks, policies::stderr_output, policies::trace> { +}; #ifdef NDEBUG -using default_registry = policies::release; +using default_registry = release_registry; #else -using default_registry = policies::debug; +using default_registry = debug_registry; #endif // BOOST_OPENMETHOD_DEFAULT_REGISTRY_HPP } // namespace boost::openmethod diff --git a/include/boost/openmethod/with_vptr.hpp b/include/boost/openmethod/with_vptr.hpp index 85163c8..3c379b2 100644 --- a/include/boost/openmethod/with_vptr.hpp +++ b/include/boost/openmethod/with_vptr.hpp @@ -76,7 +76,7 @@ class with_vptr_aux { boost_openmethod_vptr = nullptr; } - friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type { + friend auto boost_openmethod_vptr(const Class& obj, void*) -> vptr_type { if constexpr (Registry::template has_policy) { return *obj.boost_openmethod_vptr; } else { @@ -149,8 +149,8 @@ class with_vptr : detail::with_vptr_derived { -> detail::with_vptr_policy; friend auto boost_openmethod_bases(Class*) -> mp11::mp_list; - friend auto boost_openmethod_vptr(const Class& obj) -> vptr_type { - return boost_openmethod_vptr(static_cast(obj)); + friend auto boost_openmethod_vptr(const Class& obj, void* registry) -> vptr_type { + return boost_openmethod_vptr(static_cast(obj), registry); } }; diff --git a/test/test_core.cpp b/test/test_core.cpp index 28ec8e3..ce55169 100644 --- a/test/test_core.cpp +++ b/test/test_core.cpp @@ -307,3 +307,35 @@ using meet = method, virtual_)>; static_assert(has_static_offsets::value); } // namespace test_static_slots + +namespace TEST_NS { + +struct Animal { + friend auto boost_openmethod_vptr(const Animal&, void*) -> vptr_type; +}; + +static_assert(detail::has_vptr_fn); + +} // namespace TEST_NS + +namespace TEST_NS { + +using test_registry = test_registry_<__COUNTER__>; + +const detail::word value; + +struct Animal { + friend auto boost_openmethod_vptr(const Animal&, test_registry*) { + return &value; + } +}; + +static_assert(detail::has_vptr_fn); +static_assert(!detail::has_vptr_fn); + +BOOST_AUTO_TEST_CASE(vptr_from_function) { + initialize(); + BOOST_TEST(detail::acquire_vptr(Animal{}) == &value); +} + +} // namespace TEST_NS diff --git a/test/test_virtual_ptr_value_semantics.hpp b/test/test_virtual_ptr_value_semantics.hpp index 43f7743..1dd2b4f 100644 --- a/test/test_virtual_ptr_value_semantics.hpp +++ b/test/test_virtual_ptr_value_semantics.hpp @@ -72,8 +72,8 @@ struct check_illegal_smart_ops { // policies must be the same static_assert(!std::is_constructible_v< - virtual_ptr, policies::debug>, - virtual_ptr, policies::release>>); + virtual_ptr, debug_registry>, + virtual_ptr, release_registry>>); // a smart virtual_ptr cannot be constructed from a plain reference or // pointer