/******************************************************************************* * 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 "../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/arg5") { 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/arg5/cast") { namespace meta = meta_hpp; using meta::detail::uarg; SUBCASE("int[2]") { int arr[2]{1,2}; CHECK(uarg(arr).get_raw_type() == meta::resolve_type(arr)); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); } SUBCASE("const int[2]") { const int arr[2]{1,2}; CHECK(uarg(arr).get_raw_type() == meta::resolve_type(arr)); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_FALSE(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK_FALSE(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK_THROWS(std::ignore = uarg(arr).cast()); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK_THROWS(std::ignore = uarg(arr).cast()); CHECK(uarg(arr).cast() == static_cast(arr)); } SUBCASE("D[2]") { D arr[2]; CHECK(uarg(arr).get_raw_type() == meta::resolve_type(arr)); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK(uarg(arr).cast() == static_cast(arr)); } SUBCASE("const D[2]") { const D arr[2]; CHECK(uarg(arr).get_raw_type() == meta::resolve_type(arr)); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_FALSE(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK_FALSE(uarg(arr).can_cast_to()); CHECK(uarg(arr).can_cast_to()); CHECK_THROWS(std::ignore = uarg(arr).cast()); CHECK(uarg(arr).cast() == static_cast(arr)); CHECK_THROWS(std::ignore = uarg(arr).cast()); CHECK(uarg(arr).cast() == static_cast(arr)); } SUBCASE("&") { using T = D[2]; static T src{}; { auto LV = []() -> T& { return src; }; CHECK(uarg{LV()}.get_raw_type() == meta::resolve_type()); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_NOTHROW([](A*){}(LV())); CHECK_NOTHROW([](const A*){}(LV())); CHECK_NOTHROW([](A* const){}(LV())); CHECK_NOTHROW([](const A* const){}(LV())); CHECK(uarg(LV()).cast() == static_cast(src)); CHECK(uarg(LV()).cast() == static_cast(src)); CHECK(uarg(LV()).cast() == static_cast(src)); CHECK(uarg(LV()).cast() == static_cast(src)); } { auto CLV = []() -> const T& { return src; }; CHECK(uarg{CLV()}.get_raw_type() == meta::resolve_type()); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_THROWS(std::ignore = uarg(CLV()).cast()); CHECK(uarg(CLV()).cast() == static_cast(src)); CHECK_THROWS(std::ignore = uarg(CLV()).cast()); CHECK(uarg(CLV()).cast() == static_cast(src)); } { auto XV = []() -> T&& { return std::move(src); }; CHECK(uarg{XV()}.get_raw_type() == meta::resolve_type()); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); CHECK(uarg(XV()).cast() == static_cast(src)); CHECK(uarg(XV()).cast() == static_cast(src)); CHECK(uarg(XV()).cast() == static_cast(src)); CHECK(uarg(XV()).cast() == static_cast(src)); } { auto CXV = []() -> const T&& { return std::move(src); }; CHECK(uarg{CXV()}.get_raw_type() == meta::resolve_type()); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); CHECK_THROWS(std::ignore = uarg(CXV()).cast()); CHECK(uarg(CXV()).cast() == static_cast(src)); CHECK_THROWS(std::ignore = uarg(CXV()).cast()); CHECK(uarg(CXV()).cast() == static_cast(src)); } } SUBCASE("*") { { static D arr[2]{}; 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); CHECK(uarg{arr}.can_cast_to()); CHECK(uarg{arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK(&uarg{arr}.cast() == &arr); CHECK(&uarg{arr}.cast() == &arr); CHECK(uarg{&arr}.cast() == &arr); CHECK(uarg{&arr}.cast() == &arr); CHECK(uarg{&arr}.cast() == &arr); CHECK(uarg{&arr}.cast() == &arr); } { static const D arr[2]{}; 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); CHECK_FALSE(uarg{arr}.can_cast_to()); CHECK(uarg{arr}.can_cast_to()); CHECK_FALSE(uarg{&arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK_FALSE(uarg{&arr}.can_cast_to()); CHECK(uarg{&arr}.can_cast_to()); CHECK_THROWS(std::ignore = &uarg{arr}.cast()); CHECK(&uarg{arr}.cast() == &arr); CHECK_THROWS(std::ignore = uarg{&arr}.cast()); CHECK(uarg{&arr}.cast() == &arr); CHECK_THROWS(std::ignore = uarg{&arr}.cast()); CHECK(uarg{&arr}.cast() == &arr); } } }