// 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 core #include using namespace boost::openmethod; using namespace boost::openmethod::detail; namespace mp11 = boost::mp11; // clang-format off namespace test_virtual { struct base { virtual ~base() {} }; struct a : base {}; struct b : base {}; struct c : base {}; struct d : base {}; struct e : base {}; struct f : base {}; static_assert( std::is_same_v< virtual_traits::virtual_type, base>); static_assert( std::is_same_v< virtual_traits::virtual_type, base>); static_assert( std::is_same_v< virtual_traits::virtual_type, base>); static_assert( std::is_same_v< virtual_traits::virtual_type, void>); static_assert( std::is_same_v< boost::mp11::mp_filter< is_virtual, mp11::mp_list< virtual_, b, virtual_ > >, mp11::mp_list< virtual_, virtual_ > >); static_assert( std::is_same_v< remove_virtual>, a& >); static_assert( std::is_same_v< virtual_type, a >); static_assert( std::is_same_v< boost::mp11::mp_transform< remove_virtual, mp11::mp_list< virtual_, virtual_ > >, mp11::mp_list >); static_assert( std::is_same_v< boost::mp11::mp_transform_q< boost::mp11::mp_bind_back, boost::mp11::mp_transform< remove_virtual, mp11::mp_list< virtual_, virtual_ > > >, mp11::mp_list >); static_assert( std::is_same_v< boost::mp11::mp_transform_q< boost::mp11::mp_bind_back, boost::mp11::mp_transform< remove_virtual, boost::mp11::mp_filter< is_virtual, mp11::mp_list< virtual_, b, virtual_ > > > >, mp11::mp_list >); // clang-format on static_assert(std::is_same_v< virtual_types, b, virtual_>>, mp11::mp_list>); static_assert(detail::is_policy); struct not_a_policy {}; static_assert(!detail::is_policy); BOOST_AUTO_TEST_CASE(test_policy) { { // test is_policy_compatible struct policy1 : default_policy::fork {}; struct policy2 : default_policy::fork {}; static_assert(detail::is_policy_compatible< policy1, virtual_ptr>::value); static_assert(detail::is_policy_compatible::value); static_assert(!detail::is_policy_compatible< policy1, virtual_ptr>::value); } { // check that forked policy does not share static data with original struct policy : default_policy::fork {}; BOOST_TEST(&policy::methods != &default_policy::methods); BOOST_TEST(&policy::classes != &default_policy::classes); BOOST_TEST( &policy::static_vptr != &default_policy::static_vptr); BOOST_TEST(&policy::dispatch_data != &default_policy::dispatch_data); } { // check that adding a facet keeps static data from original struct policy : default_policy::add {}; BOOST_TEST(&policy::methods == &default_policy::methods); BOOST_TEST(&policy::classes == &default_policy::classes); BOOST_TEST( &policy::static_vptr == &default_policy::static_vptr); BOOST_TEST(&policy::dispatch_data == &default_policy::dispatch_data); } } BOOST_AUTO_TEST_CASE(test_type_id_list) { type_id expected[] = {type_id(&typeid(a)), type_id(&typeid(b))}; auto iter = type_id_list, default_policy>::begin; auto last = type_id_list, default_policy>::end; BOOST_TEST_REQUIRE(last - iter == 2); BOOST_TEST_REQUIRE(*iter++ == type_id(&typeid(a))); BOOST_TEST_REQUIRE(*iter++ == type_id(&typeid(b))); } } // namespace test_virtual namespace test_macros { // Check that macros can handle commas in parameter and return types. struct Animal { virtual ~Animal() = default; }; BOOST_OPENMETHOD(poke, (virtual_), std::tuple); } // namespace test_macros namespace casts { struct Animal { virtual ~Animal() { } int a{1}; }; struct Mammal : virtual Animal { int m{2}; }; struct Carnivore : virtual Animal { int c{3}; }; struct Dog : Mammal, Carnivore { int d{4}; }; const void* mammal_this(const Mammal& obj) { return &obj; } const void* carnivore_this(const Carnivore& obj) { return &obj; } const void* dog_this(const Dog& obj) { return &obj; } BOOST_AUTO_TEST_CASE(casts) { Dog dog; const Animal& animal = dog; const Mammal& mammal = dog; const Carnivore& carnivore = dog; BOOST_TEST( (&virtual_traits::cast( animal) .m) == &dog.m); BOOST_TEST( (&virtual_traits::cast( animal) .c) == &dog.c); BOOST_TEST( (&virtual_traits::cast( animal) .m) == &dog.m); BOOST_TEST( (&virtual_traits::cast( animal) .d) == &dog.d); BOOST_TEST( (&virtual_traits::cast( mammal) .d) == &dog.d); BOOST_TEST( (&virtual_traits::cast( carnivore) .c) == &dog.c); using voidp = const void*; using virtual_animal_t = virtual_type; static_assert(std::is_same_v, "animal"); using virtual_mammal_t = virtual_type; static_assert(std::is_same_v, "mammal"); } } // namespace casts namespace test_use_classes { struct Animal {}; struct Dog : public Animal {}; struct Bulldog : public Dog {}; struct Cat : public Animal {}; struct Dolphin : public Animal {}; static_assert( std::is_same_v< inheritance_map, mp11::mp_list< mp11::mp_list, mp11::mp_list, mp11::mp_list, mp11::mp_list, mp11::mp_list>>); static_assert( std::is_same_v< use_classes::tuple_type, std::tuple< class_declaration_aux< default_policy, mp11::mp_list>, class_declaration_aux< default_policy, mp11::mp_list>, class_declaration_aux< default_policy, mp11::mp_list>, class_declaration_aux< default_policy, mp11::mp_list>, class_declaration_aux< default_policy, mp11::mp_list>>>); } // namespace test_use_classes namespace facets { using namespace policies; struct key1; struct key2; struct alt_rtti {}; static_assert( std::is_same_v>::type, domain>); struct policy1 : basic_policy {}; struct policy2 : policy1::fork {}; struct policy3 : policy1::fork::replace {}; static_assert(std::is_same_v>); static_assert(std::is_same_v>); } // namespace facets // ----------------------------------------------------------------------------- // static_slots namespace test_static_slots { struct Animal; } namespace boost { namespace openmethod { namespace detail { template<> struct static_offsets, virtual_)>> { static constexpr std::size_t slots[] = {0, 1}; }; } // namespace detail } // namespace openmethod } // namespace boost namespace test_static_slots { struct Animal { virtual ~Animal() { } }; using poke = method)>; static_assert(!has_static_offsets::value); using meet = method, virtual_)>; static_assert(has_static_offsets::value); } // namespace test_static_slots