/******************************************************************************* * 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, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ #include "../meta_untests.hpp" namespace { struct A { A() = default; virtual ~A() = default; A(A&&) = delete; A(const A&) = delete; A& operator=(A&&) = delete; A& operator=(const A&) = delete; int i = 1; }; struct B : virtual A { int bi = 2; }; struct C : virtual A { int ci = 3; }; struct D : B, C { int di = 4; }; } TEST_CASE("meta/meta_utilities/arg7") { namespace meta = meta_hpp; // * <- B <- * // A D // * <- C <- * meta::class_(); meta::class_().base_(); meta::class_().base_(); meta::class_().base_().base_(); } TEST_CASE("meta/meta_utilities/arg7/cast/to_void") { namespace meta = meta_hpp; using meta::detail::arg; SUBCASE("int* -> void*") { int i{42}; static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(arg{&i}.can_cast_to()); CHECK(arg{&i}.can_cast_to()); CHECK(arg{&i}.cast() == &i); CHECK(arg{&i}.cast() == &i); } SUBCASE("const int* -> void*") { const int i{42}; static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_FALSE(arg{&i}.can_cast_to()); CHECK(arg{&i}.can_cast_to()); CHECK_THROWS(std::ignore = arg{&i}.cast()); CHECK(arg{&i}.cast() == &i); } SUBCASE("D* -> void*") { D d; static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(arg{&d}.can_cast_to()); CHECK(arg{&d}.can_cast_to()); CHECK(arg{&d}.cast() == &d); CHECK(arg{&d}.cast() == &d); } SUBCASE("const D* -> void*") { const D d; static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_FALSE(arg{&d}.can_cast_to()); CHECK(arg{&d}.can_cast_to()); CHECK_THROWS(std::ignore = arg{&d}.cast()); CHECK(arg{&d}.cast() == &d); } SUBCASE("D[2] -> void*") { D arr[2]; static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(arg{arr}.can_cast_to()); CHECK(arg{arr}.can_cast_to()); CHECK(arg{arr}.cast() == &arr); CHECK(arg{arr}.cast() == &arr); } SUBCASE("const D[2] -> void*") { const D arr[2]; static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_FALSE(arg{arr}.can_cast_to()); CHECK(arg{arr}.can_cast_to()); CHECK_THROWS(std::ignore = arg{arr}.cast()); CHECK(arg{arr}.cast() == &arr); } } TEST_CASE("meta/meta_utilities/arg7/cast/from_nullptr") { namespace meta = meta_hpp; using meta::detail::arg; SUBCASE("nullptr -> *") { static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); std::nullptr_t n1{nullptr}; const std::nullptr_t n2{nullptr}; CHECK(arg{n1}.can_cast_to()); CHECK(arg{std::move(n1)}.can_cast_to()); CHECK(arg{n2}.can_cast_to()); CHECK(arg{std::move(n2)}.can_cast_to()); CHECK(arg{n1}.can_cast_to()); CHECK(arg{std::move(n1)}.can_cast_to()); CHECK(arg{n2}.can_cast_to()); CHECK(arg{std::move(n2)}.can_cast_to()); CHECK(arg{n1}.can_cast_to()); CHECK(arg{std::move(n1)}.can_cast_to()); CHECK(arg{n2}.can_cast_to()); CHECK(arg{std::move(n2)}.can_cast_to()); CHECK(arg{n1}.can_cast_to()); CHECK(arg{std::move(n1)}.can_cast_to()); CHECK(arg{n2}.can_cast_to()); CHECK(arg{std::move(n2)}.can_cast_to()); // CHECK(arg{n1}.cast() == nullptr); CHECK(arg{std::move(n1)}.cast() == nullptr); CHECK(arg{n2}.cast() == nullptr); CHECK(arg{std::move(n2)}.cast() == nullptr); CHECK(arg{n1}.cast() == nullptr); CHECK(arg{std::move(n1)}.cast() == nullptr); CHECK(arg{n2}.cast() == nullptr); CHECK(arg{std::move(n2)}.cast() == nullptr); CHECK(arg{n1}.cast() == nullptr); CHECK(arg{std::move(n1)}.cast() == nullptr); CHECK(arg{n2}.cast() == nullptr); CHECK(arg{std::move(n2)}.cast() == nullptr); CHECK(arg{n1}.cast() == nullptr); CHECK(arg{std::move(n1)}.cast() == nullptr); CHECK(arg{n2}.cast() == nullptr); CHECK(arg{std::move(n2)}.cast() == nullptr); } }