// 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 #include #include #define BOOST_TEST_MODULE openmethod #include using namespace boost::openmethod; namespace polymorphic { struct Animal { virtual ~Animal() { } }; struct Dog : Animal {}; BOOST_OPENMETHOD_CLASSES(Animal, Dog); BOOST_OPENMETHOD(poke, (virtual_ptr), void); void instiantiate_poke(virtual_ptr snoopy) { poke(snoopy); } BOOST_AUTO_TEST_CASE(virtual_ptr_examples_polymorphic) { { initialize(trace()); { virtual_ptr p{nullptr}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { Dog snoopy; Animal& animal = snoopy; virtual_ptr p = animal; BOOST_TEST(p.get() == &snoopy); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { Dog snoopy; Animal* animal = &snoopy; virtual_ptr p = animal; BOOST_TEST(p.get() == &snoopy); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { virtual_ptr p{nullptr}; Dog snoopy; Animal* animal = &snoopy; p = animal; BOOST_TEST(p.get() == &snoopy); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { Dog snoopy; virtual_ptr p = final_virtual_ptr(snoopy); p = nullptr; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } } } BOOST_AUTO_TEST_CASE(smart_virtual_ptr_examples) { initialize(); { virtual_ptr> p; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { virtual_ptr> p{nullptr}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { const std::shared_ptr snoopy = std::make_shared(); virtual_ptr> p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { std::shared_ptr snoopy = std::make_shared(); virtual_ptr> p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { std::shared_ptr snoopy = std::make_shared(); Dog* moving = snoopy.get(); virtual_ptr> p = std::move(snoopy); BOOST_TEST(p.get() == moving); BOOST_TEST(p.vptr() == default_registry::static_vptr); BOOST_TEST(snoopy.get() == nullptr); } { const virtual_ptr> snoopy = make_shared_virtual(); virtual_ptr> p = std::move(snoopy); BOOST_TEST(snoopy.get() != nullptr); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { virtual_ptr> snoopy = make_shared_virtual(); Dog* moving = snoopy.get(); virtual_ptr> p = std::move(snoopy); BOOST_TEST(p.get() == moving); BOOST_TEST(p.vptr() == default_registry::static_vptr); BOOST_TEST(snoopy.get() == nullptr); BOOST_TEST(snoopy.vptr() == nullptr); } { virtual_ptr> p = make_shared_virtual(); p = nullptr; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); BOOST_TEST((p == virtual_ptr>())); } { const virtual_ptr> snoopy = make_shared_virtual(); virtual_ptr> p; p = snoopy; BOOST_TEST(p.get() != nullptr); BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); BOOST_TEST(snoopy.vptr() == default_registry::static_vptr); } { virtual_ptr> snoopy = make_shared_virtual(); Dog* moving = snoopy.get(); virtual_ptr> p; p = std::move(snoopy); BOOST_TEST(p.get() == moving); BOOST_TEST(p.vptr() == default_registry::static_vptr); BOOST_TEST(snoopy.get() == nullptr); BOOST_TEST(snoopy.vptr() == nullptr); } } } // namespace polymorphic namespace non_polymorphic { struct Animal {}; // polymorphic not required struct Dog : Animal {}; // polymorphic not required BOOST_OPENMETHOD_CLASSES(Animal, Dog); // codecov:ignore:start BOOST_OPENMETHOD(poke, (virtual_ptr), void); void instantiate_poke(virtual_ptr snoopy) { poke(snoopy); } // codecov:ignore:end BOOST_AUTO_TEST_CASE(virtual_ptr_examples_non_polymorphic) { { initialize(); { Dog snoopy; virtual_ptr dog = final_virtual_ptr(snoopy); virtual_ptr p(dog); BOOST_TEST(p.get() == &snoopy); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { Dog snoopy; virtual_ptr dog = final_virtual_ptr(snoopy); virtual_ptr p{nullptr}; p = dog; BOOST_TEST(p.get() == &snoopy); BOOST_TEST(p.vptr() == default_registry::static_vptr); } { virtual_ptr> snoopy = make_shared_virtual(); virtual_ptr p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); } static_assert( std::is_constructible_v< shared_virtual_ptr, virtual_ptr> == false); { virtual_ptr> snoopy = make_shared_virtual(); virtual_ptr p; p = snoopy; BOOST_TEST(p.get() == snoopy.get()); BOOST_TEST(p.vptr() == default_registry::static_vptr); } static_assert( std::is_assignable_v< shared_virtual_ptr&, virtual_ptr> == false); } } } // namespace non_polymorphic