/******************************************************************************* * This file is part of the "https://github.com/blackmatov/meta.hpp" * For conditions of distribution and use, see copyright notice in LICENSE.md * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ #include #include namespace { struct A { std::string a{"a"}; }; struct B0 : virtual A { std::string b0{"b0"}; }; struct B1 : virtual A { std::string b1{"b1"}; }; struct C : B0, B1 { std::string c{"c"}; }; struct D0 : C { std::string d0{"d0"}; }; struct E0 : D0 { std::string e0{"e0"}; }; struct D1 : C { std::string d1{"d1"}; }; struct E1 : D1 { std::string e1{"e1"}; }; } TEST_CASE("meta/meta_features/multiple2/_") { namespace meta = meta_hpp; meta::class_().base_(); meta::class_().base_(); meta::class_().base_(); meta::class_().base_(); meta::class_().base_(); meta::class_().base_(); meta::class_().base_(); // * <- B0 <- * * <- D0 * <- E0 // A C // * <- B1 <- * * <- D1 * <- E1 } TEST_CASE("meta/meta_features/multiple2") { namespace meta = meta_hpp; const meta::class_type A_type = meta::resolve_type(); const meta::class_type B0_type = meta::resolve_type(); const meta::class_type B1_type = meta::resolve_type(); const meta::class_type C_type = meta::resolve_type(); const meta::class_type D0_type = meta::resolve_type(); const meta::class_type D1_type = meta::resolve_type(); const meta::class_type E0_type = meta::resolve_type(); const meta::class_type E1_type = meta::resolve_type(); REQUIRE(A_type); REQUIRE(B0_type); REQUIRE(B1_type); REQUIRE(C_type); REQUIRE(D0_type); REQUIRE(D1_type); REQUIRE(E0_type); REQUIRE(E1_type); SUBCASE("is_base_of") { CHECK(!A_type.is_base_of(A_type)); CHECK(A_type.is_base_of(B0_type)); CHECK(A_type.is_base_of(B1_type)); CHECK(A_type.is_base_of(C_type)); CHECK(A_type.is_base_of(D0_type)); CHECK(A_type.is_base_of(D1_type)); CHECK(A_type.is_base_of(E0_type)); CHECK(A_type.is_base_of(E1_type)); CHECK(!B0_type.is_base_of(A_type)); CHECK(!B0_type.is_base_of(B0_type)); CHECK(!B0_type.is_base_of(B1_type)); CHECK(B0_type.is_base_of(C_type)); CHECK(B0_type.is_base_of(D0_type)); CHECK(B0_type.is_base_of(D1_type)); CHECK(B0_type.is_base_of(E0_type)); CHECK(B0_type.is_base_of(E1_type)); CHECK(!B1_type.is_base_of(A_type)); CHECK(!B1_type.is_base_of(B0_type)); CHECK(!B1_type.is_base_of(B1_type)); CHECK(B1_type.is_base_of(C_type)); CHECK(B1_type.is_base_of(D0_type)); CHECK(B1_type.is_base_of(D1_type)); CHECK(B1_type.is_base_of(E0_type)); CHECK(B1_type.is_base_of(E1_type)); CHECK(!C_type.is_base_of(A_type)); CHECK(!C_type.is_base_of(B0_type)); CHECK(!C_type.is_base_of(B1_type)); CHECK(!C_type.is_base_of(C_type)); CHECK(C_type.is_base_of(D0_type)); CHECK(C_type.is_base_of(D1_type)); CHECK(C_type.is_base_of(E0_type)); CHECK(C_type.is_base_of(E1_type)); CHECK(!D0_type.is_base_of(A_type)); CHECK(!D0_type.is_base_of(B0_type)); CHECK(!D0_type.is_base_of(B1_type)); CHECK(!D0_type.is_base_of(C_type)); CHECK(!D0_type.is_base_of(D0_type)); CHECK(!D0_type.is_base_of(D1_type)); CHECK(D0_type.is_base_of(E0_type)); CHECK(!D0_type.is_base_of(E1_type)); CHECK(!D1_type.is_base_of(A_type)); CHECK(!D1_type.is_base_of(B0_type)); CHECK(!D1_type.is_base_of(B1_type)); CHECK(!D1_type.is_base_of(C_type)); CHECK(!D1_type.is_base_of(D0_type)); CHECK(!D1_type.is_base_of(D1_type)); CHECK(!D1_type.is_base_of(E0_type)); CHECK(D1_type.is_base_of(E1_type)); CHECK(!E0_type.is_base_of(A_type)); CHECK(!E0_type.is_base_of(B0_type)); CHECK(!E0_type.is_base_of(B1_type)); CHECK(!E0_type.is_base_of(C_type)); CHECK(!E0_type.is_base_of(D0_type)); CHECK(!E0_type.is_base_of(D1_type)); CHECK(!E0_type.is_base_of(E0_type)); CHECK(!E0_type.is_base_of(E1_type)); CHECK(!E1_type.is_base_of(A_type)); CHECK(!E1_type.is_base_of(B0_type)); CHECK(!E1_type.is_base_of(B1_type)); CHECK(!E1_type.is_base_of(C_type)); CHECK(!E1_type.is_base_of(D0_type)); CHECK(!E1_type.is_base_of(D1_type)); CHECK(!E1_type.is_base_of(E0_type)); CHECK(!E1_type.is_base_of(E1_type)); } SUBCASE("pointer_upcast") { using meta::detail::type_registry; using meta::detail::pointer_upcast; type_registry& r{type_registry::instance()}; { A a; CHECK(pointer_upcast(r, &a) == &a); CHECK(pointer_upcast(r, &a)->a == "a"); CHECK_FALSE(pointer_upcast(r, &a)); CHECK_FALSE(pointer_upcast(r, &a)); CHECK_FALSE(pointer_upcast(r, &a)); } { B0 b0; CHECK(pointer_upcast(r, &b0) == &b0); CHECK(pointer_upcast(r, &b0)->a == "a"); CHECK(pointer_upcast(r, &b0) == &b0); CHECK(pointer_upcast(r, &b0)->b0 == "b0"); CHECK_FALSE(pointer_upcast(r, &b0)); CHECK_FALSE(pointer_upcast(r, &b0)); } { B1 b1; CHECK(pointer_upcast(r, &b1) == &b1); CHECK(pointer_upcast(r, &b1)->a == "a"); CHECK_FALSE(pointer_upcast(r, &b1)); CHECK(pointer_upcast(r, &b1) == &b1); CHECK(pointer_upcast(r, &b1)->b1 == "b1"); CHECK_FALSE(pointer_upcast(r, &b1)); } { C c; CHECK(pointer_upcast(r, &c) == &c); CHECK(pointer_upcast(r, &c)->a == "a"); CHECK(pointer_upcast(r, &c) == &c); CHECK(pointer_upcast(r, &c)->b0 == "b0"); CHECK(pointer_upcast(r, &c) == &c); CHECK(pointer_upcast(r, &c)->b1 == "b1"); CHECK(pointer_upcast(r, &c) == &c); CHECK(pointer_upcast(r, &c)->c == "c"); CHECK_FALSE(pointer_upcast(r, &c)); CHECK_FALSE(pointer_upcast(r, &c)); CHECK_FALSE(pointer_upcast(r, &c)); CHECK_FALSE(pointer_upcast(r, &c)); } { E0 e0; CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->a == "a"); CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->b0 == "b0"); CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->b1 == "b1"); CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->c == "c"); CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->d0 == "d0"); CHECK_FALSE(pointer_upcast(r, &e0)); CHECK(pointer_upcast(r, &e0) == &e0); CHECK(pointer_upcast(r, &e0)->e0 == "e0"); CHECK_FALSE(pointer_upcast(r, &e0)); } { E1 e1; CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->a == "a"); CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->b0 == "b0"); CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->b1 == "b1"); CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->c == "c"); CHECK_FALSE(pointer_upcast(r, &e1)); CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->d1 == "d1"); CHECK_FALSE(pointer_upcast(r, &e1)); CHECK(pointer_upcast(r, &e1) == &e1); CHECK(pointer_upcast(r, &e1)->e1 == "e1"); } } }