diff --git a/TODO.md b/TODO.md index a7dfaf4..7bad6d4 100644 --- a/TODO.md +++ b/TODO.md @@ -4,7 +4,6 @@ - add return value policy - add meta exception class; - add conversion of nullptr to any pointers; -- add conversion of any pointers to void pointer ( identically cv-qualified ); - void value? - all string to hash? diff --git a/headers/meta.hpp/meta_utilities/arg.hpp b/headers/meta.hpp/meta_utilities/arg.hpp index 259bb42..f081759 100644 --- a/headers/meta.hpp/meta_utilities/arg.hpp +++ b/headers/meta.hpp/meta_utilities/arg.hpp @@ -107,8 +107,10 @@ namespace meta_hpp::detail const any_type& to_data_type = to_type_ptr.get_data_type(); const any_type& from_data_type = from_type_array.get_data_type(); - if ( is_a(to_data_type, from_data_type) && to_type_ptr_readonly >= from_type_array_readonly ) { - return true; + if ( to_type_ptr_readonly >= from_type_array_readonly ) { + if ( to_data_type.is_void() || is_a(to_data_type, from_data_type) ) { + return true; + } } } @@ -122,8 +124,10 @@ namespace meta_hpp::detail const any_type& to_data_type = to_type_ptr.get_data_type(); const any_type& from_data_type = from_type_ptr.get_data_type(); - if ( is_a(to_data_type, from_data_type) && to_type_ptr_readonly >= from_type_ptr_readonly ) { - return true; + if ( to_type_ptr_readonly >= from_type_ptr_readonly ) { + if ( to_data_type.is_void() || is_a(to_data_type, from_data_type) ) { + return true; + } } } } @@ -209,7 +213,7 @@ namespace meta_hpp::detail const any_type& to_data_type = to_type_ptr.get_data_type(); const any_type& from_data_type = from_type_array.get_data_type(); - if ( to_data_type == from_data_type ) { + if ( to_data_type.is_void() || to_data_type == from_data_type ) { return static_cast(data_); } @@ -231,7 +235,7 @@ namespace meta_hpp::detail void** from_data_ptr = static_cast(data_); - if ( to_data_type == from_data_type ) { + if ( to_data_type.is_void() || to_data_type == from_data_type ) { return static_cast(*from_data_ptr); } diff --git a/untests/meta_utilities/arg7_tests.cpp b/untests/meta_utilities/arg7_tests.cpp new file mode 100644 index 0000000..4ffe3da --- /dev/null +++ b/untests/meta_utilities/arg7_tests.cpp @@ -0,0 +1,124 @@ +/******************************************************************************* + * 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 i = 2; + }; + + struct C : virtual A { + int i = 3; + }; + + struct D : B, C { + int i = 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") { + namespace meta = meta_hpp; + using meta::detail::arg; + + SUBCASE("int*") { + int i{42}; + + 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*") { + const int i{42}; + + 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*") { + 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*") { + 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]") { + 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]") { + 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); + } +}