// Copyright (c) 2018-2025 Jean-Louis Leroy // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) #include #define BOOST_TEST_MODULE openmethod #include #include "test_virtual_ptr_value_semantics.hpp" #include using namespace detail; BOOST_AUTO_TEST_CASE_TEMPLATE( unique_virtual_ptr_value, Registry, test_policies) { init_test(); static_assert(std::is_same_v< typename unique_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&>); { // unique_virtual_ptr(nullptr) unique_virtual_ptr p{nullptr}; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } static_assert(!construct_assign_ok, Dog>); static_assert( !construct_assign_ok, Dog&>); static_assert( !construct_assign_ok, Dog*>); static_assert(!construct_assign_ok< unique_virtual_ptr, std::unique_ptr&>); static_assert( !construct_assign_ok< unique_virtual_ptr, const std::unique_ptr&>); static_assert(!construct_assign_ok< unique_virtual_ptr, unique_virtual_ptr>); static_assert(!construct_assign_ok< unique_virtual_ptr, unique_virtual_ptr&>); static_assert( !construct_assign_ok< unique_virtual_ptr, const unique_virtual_ptr&>); { // construct from unique_ptr temporary unique_virtual_ptr p(std::make_unique()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { // derived-to-base ok? unique_virtual_ptr p(std::make_unique()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } static_assert( !construct_assign_ok< unique_virtual_ptr, const std::unique_ptr&>); static_assert(!construct_assign_ok< unique_virtual_ptr, std::unique_ptr&>); static_assert(!construct_assign_ok< unique_virtual_ptr, const unique_virtual_ptr&>); static_assert(!construct_assign_ok< unique_virtual_ptr, unique_virtual_ptr&>); static_assert(!construct_assign_ok< unique_virtual_ptr, unique_virtual_ptr&>); { // assign from smart ptr temporary unique_virtual_ptr p{nullptr}; p = std::make_unique(); BOOST_TEST(p.get() != nullptr); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { // derived-to-base ok? unique_virtual_ptr p{nullptr}; p = std::make_unique(); BOOST_TEST(p.get() != nullptr); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { // unique_virtual_ptr(unique_virtual_ptr) unique_virtual_ptr p(std::make_unique()); auto dog = p.get(); unique_virtual_ptr q(std::move(p)); BOOST_TEST(q.get() == dog); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { // derived-to-base ok? unique_virtual_ptr p(std::make_unique()); auto dog = p.get(); unique_virtual_ptr q(std::move(p)); BOOST_TEST(q.get() == dog); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { // virtual_ptr(std::unique_ptr()) unique_virtual_ptr p = std::unique_ptr(); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { unique_virtual_ptr p(std::make_unique()); p = nullptr; BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { unique_virtual_ptr p(std::make_unique()); p = std::unique_ptr(); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } #if 0 { // unique_virtual_ptr = const std::unique_ptr& unique_virtual_ptr p; const auto s = std::make_unique(); p = s; BOOST_TEST(p.get() == s.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { // unique_virtual_ptr = std::unique_ptr& unique_virtual_ptr p; auto s = std::make_unique(); p = s; BOOST_TEST(p.get() == s.get()); BOOST_TEST(p.vptr() == Registry::template static_vptr); } { // unique_virtual_ptr = std::unique_ptr&& auto s = std::make_unique(); auto p = s; unique_virtual_ptr q; q = std::move(p); BOOST_TEST(q.get() == s.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); } { // unique_virtual_ptr = std::unique_ptr&& auto s = std::make_unique(); auto p = s; unique_virtual_ptr q; q = std::move(p); BOOST_TEST(q.get() == s.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); } { // unique_virtual_ptr = unique_virtual_ptr&& auto s = std::make_unique(); unique_virtual_ptr p(s); unique_virtual_ptr q; q = std::move(p); BOOST_TEST(q.get() == s.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { // unique_virtual_ptr = unique_virtual_ptr&& auto s = std::make_unique(); unique_virtual_ptr p(s); unique_virtual_ptr q; q = std::move(p); BOOST_TEST(q.get() == s.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); BOOST_TEST(p.get() == nullptr); BOOST_TEST(p.vptr() == nullptr); } { // virtual_ptr(unique_virtual_ptr&) auto p = make_unique_virtual(); virtual_ptr q(p); BOOST_TEST(q.get() == p.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); } { // virtual_ptr = unique_virtual_ptr& const auto p = make_unique_virtual(); virtual_ptr q; q = p; BOOST_TEST(q.get() == p.get()); BOOST_TEST(q.vptr() == Registry::template static_vptr); } // illegal constructions and assignments 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*>); static_assert(!std::is_assignable_v, Dog>); static_assert( !std::is_assignable_v, Dog&&>); static_assert( !std::is_assignable_v, const Dog&>); static_assert( !std::is_assignable_v, const Dog*>); #endif } BOOST_AUTO_TEST_CASE_TEMPLATE( cast_unique_virtual_ptr_value, Class, test_classes) { init_test(); unique_virtual_ptr base = make_unique_virtual(); auto p = base.get(); auto derived = virtual_traits, default_registry>::cast< unique_virtual_ptr>(std::move(base)); BOOST_TEST(derived.get() == p); BOOST_TEST(derived.vptr() == default_registry::static_vptr); BOOST_TEST(base.get() == nullptr); } template struct check_illegal_smart_ops< std::unique_ptr, std::shared_ptr, direct_vector>; // Cannot construct or assign a virtual_ptr from a non-polymorphic object. static_assert(!construct_assign_ok< virtual_ptr>, const std::unique_ptr&>); static_assert(!construct_assign_ok< virtual_ptr>, std::unique_ptr&>); static_assert(!construct_assign_ok< virtual_ptr>, std::unique_ptr&&>); // OK to move from another virtual_ptr though, because it can be constructed // using 'final'. static_assert(construct_assign_ok< virtual_ptr>, virtual_ptr>&&>);