fix indirect virtual_ptr::final

This commit is contained in:
Jean-Louis Leroy
2025-05-18 12:43:26 -04:00
committed by Jean-Louis Leroy
parent e80d443dbf
commit da937900d9
2 changed files with 27 additions and 20 deletions

View File

@@ -357,14 +357,18 @@ inline vptr_type null_vptr = nullptr;
template<class Class, class Registry, typename = void>
class virtual_ptr_impl {
protected:
static constexpr bool use_indirect_vptrs =
Registry::template has_policy<policies::indirect_vptr>;
std::conditional_t<use_indirect_vptrs, const vptr_type*, vptr_type> vp;
Class* obj;
public:
using traits = virtual_traits<Class&, Registry>;
using element_type = Class;
static constexpr bool is_smart_ptr = false;
static constexpr bool use_indirect_vptrs =
Registry::template has_policy<policies::indirect_vptr>;
virtual_ptr_impl() = default;
explicit virtual_ptr_impl(std::nullptr_t)
@@ -422,8 +426,7 @@ class virtual_ptr_impl {
template<
class Other,
typename = std::enable_if_t<std::is_constructible_v<Class*, Other*>>>
virtual_ptr_impl(Other& other, const vptr_type& vp)
: vp(box_vptr<use_indirect_vptrs>(vp)), obj(&other) {
virtual_ptr_impl(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
}
template<
@@ -488,15 +491,11 @@ class virtual_ptr_impl {
std::is_base_of_v<Class, Other> || std::is_base_of_v<Other, Class>);
return virtual_ptr<Other, Registry>(
traits::template cast<Other&>(*obj), unbox_vptr(vp));
traits::template cast<Other&>(*obj), vp);
}
template<class, class>
friend struct virtual_traits;
protected:
std::conditional_t<use_indirect_vptrs, const vptr_type*, vptr_type> vp;
Class* obj;
};
template<class Class, class Other, class Registry, typename = void>
@@ -576,6 +575,12 @@ class virtual_ptr_impl<
obj(other) {
}
template<
class Other,
typename = std::enable_if_t<std::is_constructible_v<Class*, Other*>>>
virtual_ptr_impl(Other& other, decltype(vp) vp) : vp(vp), obj(&other) {
}
template<
class Other,
typename = std::enable_if_t<
@@ -621,6 +626,11 @@ class virtual_ptr_impl<
other.vp = box_vptr<use_indirect_vptrs>(null_vptr);
}
template<typename Arg>
virtual_ptr_impl(Arg&& obj, decltype(vp) vp)
: vp(vp), obj(std::forward<Arg>(obj)) {
}
virtual_ptr_impl& operator=(std::nullptr_t) {
obj = nullptr;
vp = box_vptr<use_indirect_vptrs>(null_vptr);
@@ -705,11 +715,6 @@ class virtual_ptr_impl<
return obj;
}
template<typename Arg>
virtual_ptr_impl(Arg&& obj, decltype(vp) other_vp)
: vp(other_vp), obj(std::forward<Arg>(obj)) {
}
template<class Other>
auto cast() & -> decltype(auto) {
static_assert(
@@ -803,7 +808,7 @@ class virtual_ptr : public detail::virtual_ptr_impl<Class, Registry> {
return virtual_ptr(
std::forward<Other>(obj),
detail::box_vptr<impl::use_indirect_vptrs>(
box_vptr<impl::use_indirect_vptrs>(
Registry::template static_vptr<other_class>));
}

View File

@@ -197,7 +197,8 @@ auto fight_bear(VirtualWarriorPtr, VirtualAxePtr, VirtualBearPtr) {
}
template<int N>
struct indirect_test_registry : test_registry_<N> {};
struct indirect_test_registry
: test_registry_<N>::template with<policies::indirect_vptr> {};
template<int N>
using policy_types =
@@ -230,12 +231,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(
Player player;
auto virtual_player = vptr_player::final(player);
BOOST_TEST(&*virtual_player == &player);
BOOST_TEST((virtual_player.vptr() == Registry::template static_vptr<Player>));
BOOST_TEST(
(virtual_player.vptr() == Registry::template static_vptr<Player>));
Bear bear;
BOOST_TEST((&*vptr_bear::final(bear)) == &bear);
BOOST_TEST(
(vptr_bear::final(bear).vptr() == Registry::template static_vptr<Bear>));
BOOST_TEST((
vptr_bear::final(bear).vptr() == Registry::template static_vptr<Bear>));
BOOST_TEST(
(vptr_player(bear).vptr() == Registry::template static_vptr<Bear>));