// 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 #include #include #include "test_util.hpp" #define BOOST_TEST_MODULE openmethod #include #include using namespace boost::openmethod; struct Player { virtual ~Player() { } }; struct Warrior : Player {}; struct Wizard : Player {}; struct Bear : Player {}; struct Object { virtual ~Object() { } }; struct Axe : Object {}; template auto poke_bear(VirtualBearPtr) { return std::string("growl"); } template auto fight_bear(VirtualWarriorPtr, VirtualAxePtr, VirtualBearPtr) { return "kill bear"; } template struct indirect_test_policy : test_policy_ {}; template using policy_types = boost::mp11::mp_list, indirect_test_policy>; struct BOOST_OPENMETHOD_NAME(poke); struct BOOST_OPENMETHOD_NAME(fight); namespace BOOST_OPENMETHOD_GENSYM { BOOST_AUTO_TEST_CASE_TEMPLATE( test_virtual_ptr, Policy, policy_types<__COUNTER__>) { BOOST_OPENMETHOD_REGISTER( use_classes); ; using poke = method< BOOST_OPENMETHOD_NAME(poke)(virtual_ptr), std::string, Policy>; BOOST_OPENMETHOD_REGISTER( typename poke::template override< poke_bear>>); initialize(); using vptr_player = virtual_ptr; static_assert(detail::is_virtual_ptr); using vptr_bear = virtual_ptr; Player player; auto virtual_player = vptr_player::final(player); BOOST_TEST(&*virtual_player == &player); BOOST_TEST((virtual_player.vptr() == Policy::template static_vptr)); Bear bear; BOOST_TEST((&*vptr_bear::final(bear)) == &bear); BOOST_TEST( (vptr_bear::final(bear).vptr() == Policy::template static_vptr)); BOOST_TEST( (vptr_player(bear).vptr() == Policy::template static_vptr)); vptr_bear virtual_bear_ptr(bear); vptr_player virtual_player_ptr = virtual_bear_ptr; struct upcast { static void fn(vptr_player) { } }; upcast::fn(virtual_bear_ptr); auto data = Policy::dispatch_data.data(); std::fill_n(data, Policy::dispatch_data.size(), 0); while (data == Policy::dispatch_data.data()) { Policy::dispatch_data.resize(2 * Policy::dispatch_data.size()); } initialize(); BOOST_TEST( (virtual_bear_ptr.vptr() == Policy::template static_vptr) == Policy::template has_facet); } } // namespace BOOST_OPENMETHOD_GENSYM namespace test_virtual_ptr_dispatch { BOOST_AUTO_TEST_CASE_TEMPLATE( test_virtual_ptr_dispatch, Policy, policy_types<__COUNTER__>) { BOOST_OPENMETHOD_REGISTER( use_classes); using poke = method< BOOST_OPENMETHOD_NAME(poke)(virtual_ptr), std::string, Policy>; BOOST_OPENMETHOD_REGISTER( typename poke::template override< poke_bear>>); using fight = method< BOOST_OPENMETHOD_NAME(fight)( virtual_ptr, virtual_ptr, virtual_ptr), std::string, Policy>; BOOST_OPENMETHOD_REGISTER( typename fight::template override, virtual_ptr, virtual_ptr>>); initialize(); Bear bear; BOOST_TEST(poke::fn(virtual_ptr(bear)) == "growl"); Warrior warrior; Axe axe; BOOST_TEST( fight::fn( virtual_ptr(warrior), virtual_ptr(axe), virtual_ptr(bear)) == "kill bear"); } } // namespace test_virtual_ptr_dispatch namespace test_shared_virtual_ptr_dispatch { BOOST_AUTO_TEST_CASE_TEMPLATE( test_virtual_ptr_dispatch, Policy, policy_types<__COUNTER__>) { BOOST_OPENMETHOD_REGISTER( use_classes); using poke = method< BOOST_OPENMETHOD_NAME(poke)(shared_virtual_ptr), std::string, Policy>; BOOST_OPENMETHOD_REGISTER( typename poke::template override< poke_bear>>); using fight = method< BOOST_OPENMETHOD_NAME(fight)( shared_virtual_ptr, shared_virtual_ptr, shared_virtual_ptr), std::string, Policy>; BOOST_OPENMETHOD_REGISTER( typename fight::template override, shared_virtual_ptr, shared_virtual_ptr>>); initialize(); auto bear = make_shared_virtual(); auto warrior = make_shared_virtual(); auto axe = make_shared_virtual(); BOOST_TEST(poke::fn(bear) == "growl"); BOOST_TEST(fight::fn(warrior, axe, bear) == "kill bear"); } } // namespace test_shared_virtual_ptr_dispatch