diff --git a/include/boost/openmethod/core.hpp b/include/boost/openmethod/core.hpp index 27f4552e..fa551ff3 100644 --- a/include/boost/openmethod/core.hpp +++ b/include/boost/openmethod/core.hpp @@ -1003,12 +1003,19 @@ struct is_virtual_ptr_aux&> : template constexpr bool is_virtual_ptr = detail::is_virtual_ptr_aux::value; +// Whether `boost_openmethod_vptr`, the customization point found by ADL, yields +// a v-table pointer for `Class` in `Registry`. The class provides it, as +// `inplace_vptr_base` does; the catch-all `boost_openmethod_vptr(...)` makes +// the question safe to ask of any class. template -constexpr bool has_vptr_fn = std::is_same_v< +constexpr bool has_adl_vptr = std::is_same_v< decltype(boost_openmethod_vptr( std::declval(), std::declval())), vptr_type>; +// `has_vptr`: whether `Traits::vptr(arg)` exists. That is how a +// `virtual_traits` specialization yields a v-table pointer, for a type that +// cannot carry an ADL overload of its own, such as `std::any`. BOOST_OPENMETHOD_DETAIL_HAS_STATIC_FN(vptr); template @@ -1018,7 +1025,7 @@ decltype(auto) acquire_vptr(const ArgType& arg) { // to the v-table pointer. The hook also returns the vptr by value, // which indirect registries cannot store (see box_vptr). static_assert( - !has_vptr_fn, + !has_adl_vptr, "do not wrap an object that has a boost_openmethod_vptr overload " "in a virtual_ptr; call methods directly on the object"); @@ -2326,7 +2333,7 @@ struct parameter_traits&, Registry> : // indentation, and because each route is worth naming. template constexpr bool has_vptr_source = - has_vptr_fn, Registry> || + has_adl_vptr, Registry> || has_vptr< virtual_traits, decltype(virtual_traits::peek(std::declval()))> || @@ -2946,7 +2953,7 @@ BOOST_FORCEINLINE auto method::vptr( } else { decltype(auto) obj = virtual_traits::peek(arg); - if constexpr (detail::has_vptr_fn) { + if constexpr (detail::has_adl_vptr) { return boost_openmethod_vptr(obj, static_cast(nullptr)); } else if constexpr ( detail::has_vptr< diff --git a/test/test_core.cpp b/test/test_core.cpp index 0a639bb4..136833fd 100644 --- a/test/test_core.cpp +++ b/test/test_core.cpp @@ -261,7 +261,7 @@ struct Animal { friend auto boost_openmethod_vptr(const Animal&, void*) -> vptr_type; }; -static_assert(detail::has_vptr_fn); +static_assert(detail::has_adl_vptr); } // namespace TEST_NS @@ -274,8 +274,8 @@ struct Animal { -> vptr_type; }; -static_assert(detail::has_vptr_fn); -static_assert(!detail::has_vptr_fn); +static_assert(detail::has_adl_vptr); +static_assert(!detail::has_adl_vptr); // The hook serves dispatch (method::vptr), not virtual_ptr: acquire_vptr // rejects classes with a boost_openmethod_vptr overload at compile time - diff --git a/test/test_dispatch_type_erasure.cpp b/test/test_dispatch_type_erasure.cpp index 7da956d8..da44b1ee 100644 --- a/test/test_dispatch_type_erasure.cpp +++ b/test/test_dispatch_type_erasure.cpp @@ -311,8 +311,8 @@ using dispatchable_ref = te::any; // the intrinsic hook is found for every any, so dispatch prefers it // over the vptr policy's hash lookup -static_assert(detail::has_vptr_fn); -static_assert(detail::has_vptr_fn); +static_assert(detail::has_adl_vptr); +static_assert(detail::has_adl_vptr); // `Dog` is registered both by the `name` overrider below and by binding // (class dedup) @@ -377,8 +377,8 @@ using dispatchable = te::any; // The hook is keyed on the registry the concept names: it is found for // `indirect_registry`, and for no other - a mismatch would fall back on the // vptr policy's hash lookup, silently losing the constant-time property. -static_assert(detail::has_vptr_fn); -static_assert(!detail::has_vptr_fn); +static_assert(detail::has_adl_vptr); +static_assert(!detail::has_adl_vptr); using name_method = method< struct name_id, std::string(virtual_),