// qright (c) 2018-2025 Jean-Louis Leroy // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt // or q at http://www.boost.org/LICENSE_1_0.txt) #include #define BOOST_TEST_MODULE openmethod #include #include #include "test_virtual_ptr_value_semantics.hpp" #include static_assert(SameSmartPtr< std::shared_ptr, std::shared_ptr, default_registry>); static_assert(!SameSmartPtr< std::shared_ptr, std::unique_ptr, default_registry>); static_assert(!SameSmartPtr< std::shared_ptr, shared_virtual_ptr>, default_registry>); BOOST_AUTO_TEST_CASE_TEMPLATE( shared_virtual_ptr_value, Registry, test_policies) { static_assert(std::is_same_v< typename shared_virtual_ptr::element_type, Animal>); static_assert(std::is_same_v< decltype(std::declval>() .get()), Animal*>); static_assert(IsSmartPtr, Registry>); static_assert(IsSmartPtr, Registry>); static_assert( std::is_same_v< decltype(*std::declval>()), Animal&>); init_test(); // construction and assignment from a plain pointer or reference is not // allowed static_assert(!construct_assign_ok, Dog>); static_assert( !construct_assign_ok, Dog&&>); static_assert( !construct_assign_ok, const Dog&>); static_assert( !construct_assign_ok, const Dog*>); // ------------------------------------------------------------------------- // construction and assignment from plain references and pointers { shared_virtual_ptr p{nullptr}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); p = *&p; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto hector = std::make_shared(); p = hector; BOOST_TEST(p.get() == hector.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto felix = std::make_shared(); p = felix; BOOST_TEST(p.get() == felix.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto hector = std::make_shared(); p = hector; BOOST_TEST(p.get() == hector.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { const auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto felix = std::make_shared(); p = felix; BOOST_TEST(p.get() == felix.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto hector = std::make_shared(); p = hector; BOOST_TEST(p.get() == hector.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto felix = std::make_shared(); p = felix; BOOST_TEST(p.get() == felix.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto hector = std::make_shared(); p = hector; BOOST_TEST(p.get() == hector.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); auto felix = std::make_shared(); p = felix; BOOST_TEST(p.get() == felix.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } // shared_virtual_ptr p{Dog()}; static_assert( !construct_assign_ok, Dog&&>); // ------------------------------------------------------------------------- // construction and assignment from other shared_virtual_ptr { // shared_virtual_ptr(const shared_virtual_ptr&) auto snoopy = std::make_shared(); const shared_virtual_ptr p(snoopy); shared_virtual_ptr q(p); BOOST_TEST(q.get() == snoopy.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); } { // shared_virtual_ptr(shared_virtual_ptr&) auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); shared_virtual_ptr q(p); BOOST_TEST(q.get() == snoopy.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); } { // shared_virtual_ptr(shared_virtual_ptr&&) auto snoopy = std::make_shared(); shared_virtual_ptr p(snoopy); shared_virtual_ptr q(std::move(p)); BOOST_TEST(q.get() == snoopy.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { // shared_virtual_ptr(const shared_virtual_ptr&) auto snoopy = std::make_shared(); const shared_virtual_ptr p(snoopy); shared_virtual_ptr base(p); BOOST_TEST(base.get() == snoopy.get()); BOOST_TEST(base.vptr() == Registry::template static_vptr); } { // shared_virtual_ptr(const shared_virtual_ptr&) auto snoopy = std::make_shared(); const shared_virtual_ptr p(snoopy); shared_virtual_ptr const_q(p); BOOST_TEST(const_q.get() == snoopy.get()); BOOST_TEST(const_q.vptr() == Registry::template static_vptr); } { // shared_virtual_ptr(const shared_virtual_ptr&) auto snoopy = std::make_shared(); const shared_virtual_ptr p(snoopy); shared_virtual_ptr const_base_q(p); BOOST_TEST(const_base_q.get() == snoopy.get()); BOOST_TEST(const_base_q.vptr() == Registry::template static_vptr); } { // shared_virtual_ptr() shared_virtual_ptr p{nullptr}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { shared_virtual_ptr p{std::shared_ptr()}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } // ------------------------------------------------------------------------- // assignment { shared_virtual_ptr p; auto snoopy = std::make_shared(); p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { shared_virtual_ptr p; auto snoopy = std::make_shared(); p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { auto p = make_shared_virtual(); p = nullptr; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { auto p = make_shared_virtual(); p = std::shared_ptr(); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } static_assert( !construct_assign_ok, const Dog&>); static_assert( !construct_assign_ok, const Dog*>); } BOOST_AUTO_TEST_CASE(cast_shared_ptr_value) { init_test(); std::shared_ptr animal = std::make_shared(); auto dog = virtual_traits, default_registry>::cast< std::shared_ptr>(animal); BOOST_TEST(dog.get() == animal.get()); } BOOST_AUTO_TEST_CASE(cast_shared_ptr_lvalue_reference) { init_test(); std::shared_ptr animal = std::make_shared(); auto dog = virtual_traits&, default_registry>::cast< const std::shared_ptr&>(animal); BOOST_TEST(dog.get() == animal.get()); } bool cast_moves() { init_test(); std::shared_ptr animal = std::make_shared(); (void)std::static_pointer_cast(animal); return animal.get() == nullptr; } BOOST_AUTO_TEST_CASE(cast_shared_ptr_xvalue_reference) { init_test(); std::shared_ptr animal = std::make_shared(); auto p = animal.get(); auto dog = virtual_traits, default_registry>::cast< std::shared_ptr>(std::move(animal)); BOOST_TEST(dog.get() == p); if (cast_moves()) { BOOST_TEST(animal.get() == nullptr); } } BOOST_AUTO_TEST_CASE_TEMPLATE( cast_shared_virtual_ptr_value, Class, test_classes) { init_test(); shared_virtual_ptr base = make_shared_virtual(); auto derived = virtual_traits, default_registry>::cast< shared_virtual_ptr>(base); BOOST_TEST(derived.get() == base.get()); BOOST_TEST(base.vptr() == default_registry::static_vptr); BOOST_TEST(derived.vptr() == default_registry::static_vptr); } BOOST_AUTO_TEST_CASE_TEMPLATE( cast_shared_virtual_ptr_lvalue_reference, Class, test_classes) { init_test(); shared_virtual_ptr base = make_shared_virtual(); auto derived = virtual_traits&, default_registry>:: cast>(base); BOOST_TEST(derived.get() == base.get()); BOOST_TEST(base.vptr() == default_registry::static_vptr); BOOST_TEST(derived.vptr() == default_registry::static_vptr); } BOOST_AUTO_TEST_CASE_TEMPLATE( cast_shared_virtual_ptr_xvalue_reference, Class, test_classes) { init_test(); shared_virtual_ptr base = make_shared_virtual(); auto p = base.get(); auto derived = virtual_traits, default_registry>::cast< shared_virtual_ptr>(std::move(base)); BOOST_TEST(derived.get() == p); BOOST_TEST(derived.vptr() == default_registry::static_vptr); if (cast_moves()) { BOOST_TEST(base.get() == nullptr); } } template struct check_illegal_smart_ops< std::shared_ptr, std::unique_ptr, direct_vector>; // Cannot construct or assign a virtual_ptr from a non-polymorphic object. static_assert(!construct_assign_ok< virtual_ptr>, const std::shared_ptr&>); static_assert(!construct_assign_ok< virtual_ptr>, std::shared_ptr&>); static_assert(!construct_assign_ok< virtual_ptr>, std::shared_ptr&&>); // OK from another virtual_ptr though, because it can be constructed using // 'final'. static_assert(std::is_assignable_v< virtual_ptr>, const virtual_ptr>&>); static_assert(construct_assign_ok< virtual_ptr>, virtual_ptr>&>); static_assert(construct_assign_ok< virtual_ptr>, virtual_ptr>&&>);