mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
array arg support
This commit is contained in:
@@ -87,6 +87,21 @@ namespace meta_hpp::detail
|
|||||||
};
|
};
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<To> ) {
|
if constexpr ( std::is_pointer_v<To> ) {
|
||||||
|
if ( to_type.is_pointer() && from_type.is_array() ) {
|
||||||
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
|
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
|
|
||||||
|
const array_type& from_type_array = from_type.as_array();
|
||||||
|
const bool from_type_array_readonly = is_const();
|
||||||
|
|
||||||
|
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.is_pointer() && from_type.is_pointer() ) {
|
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
||||||
const pointer_type& to_type_ptr = to_type.as_pointer();
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly);
|
||||||
@@ -177,6 +192,27 @@ namespace meta_hpp::detail
|
|||||||
const any_type& to_type = resolve_type<to_raw_type>();
|
const any_type& to_type = resolve_type<to_raw_type>();
|
||||||
|
|
||||||
if constexpr ( std::is_pointer_v<To> ) {
|
if constexpr ( std::is_pointer_v<To> ) {
|
||||||
|
if ( to_type.is_pointer() && from_type.is_array() ) {
|
||||||
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
|
const array_type& from_type_array = from_type.as_array();
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
void* to_ptr = static_cast<void*>(data_);
|
||||||
|
return static_cast<to_raw_type_cv>(to_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( to_data_type.is_class() && from_data_type.is_class() ) {
|
||||||
|
const class_type& to_data_class = to_data_type.as_class();
|
||||||
|
const class_type& from_data_class = from_data_type.as_class();
|
||||||
|
|
||||||
|
void* to_ptr = detail::pointer_upcast(data_, from_data_class, to_data_class);
|
||||||
|
return static_cast<to_raw_type_cv>(to_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
if ( to_type.is_pointer() && from_type.is_pointer() ) {
|
||||||
const pointer_type& to_type_ptr = to_type.as_pointer();
|
const pointer_type& to_type_ptr = to_type.as_pointer();
|
||||||
const pointer_type& from_type_ptr = from_type.as_pointer();
|
const pointer_type& from_type_ptr = from_type.as_pointer();
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* 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_manuals.hpp"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("meta/meta_examples/arrays") {
|
|
||||||
namespace meta = meta_hpp;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* 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_manuals.hpp"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("meta/meta_examples/numbers") {
|
|
||||||
namespace meta = meta_hpp;
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,11 @@ namespace
|
|||||||
static int ilength2(const ivec2& v) noexcept {
|
static int ilength2(const ivec2& v) noexcept {
|
||||||
return v.x * v.x + v.y * v.y;
|
return v.x * v.x + v.y * v.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int arg_bounded_arr(ivec2 vs[2]) { return vs[0].x + vs[0].y + vs[1].x + vs[1].y; }
|
||||||
|
static int arg_unbounded_arr(ivec2 vs[]) { return vs[0].x + vs[0].y + vs[1].x + vs[1].y; }
|
||||||
|
static int arg_bounded_const_arr(const ivec2 vs[2]) { return vs[0].x + vs[0].y + vs[1].x + vs[1].y; }
|
||||||
|
static int arg_unbounded_const_arr(const ivec2 vs[]) { return vs[0].x + vs[0].y + vs[1].x + vs[1].y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const ivec2& l, const ivec2& r) noexcept {
|
bool operator==(const ivec2& l, const ivec2& r) noexcept {
|
||||||
@@ -31,7 +36,11 @@ TEST_CASE("meta/meta_states/function") {
|
|||||||
|
|
||||||
meta::class_<ivec2>()
|
meta::class_<ivec2>()
|
||||||
.function_("iadd", &ivec2::iadd)
|
.function_("iadd", &ivec2::iadd)
|
||||||
.function_("ilength2", &ivec2::ilength2);
|
.function_("ilength2", &ivec2::ilength2)
|
||||||
|
.function_("arg_bounded_arr", &ivec2::arg_bounded_arr)
|
||||||
|
.function_("arg_unbounded_arr", &ivec2::arg_unbounded_arr)
|
||||||
|
.function_("arg_bounded_const_arr", &ivec2::arg_bounded_const_arr)
|
||||||
|
.function_("arg_unbounded_const_arr", &ivec2::arg_unbounded_const_arr);
|
||||||
|
|
||||||
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
|
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
|
||||||
REQUIRE(ivec2_type);
|
REQUIRE(ivec2_type);
|
||||||
@@ -104,4 +113,120 @@ TEST_CASE("meta/meta_states/function") {
|
|||||||
CHECK(func.invoke(ivec2{2,3}));
|
CHECK(func.invoke(ivec2{2,3}));
|
||||||
CHECK(func.invoke(ivec2{2,3}).value() == 13);
|
CHECK(func.invoke(ivec2{2,3}).value() == 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_arr") {
|
||||||
|
ivec2 bounded_arr[2]{{1,2},{3,4}};
|
||||||
|
ivec2* unbounded_arr = bounded_arr;
|
||||||
|
|
||||||
|
const ivec2 bounded_const_arr[2]{{1,2},{3,4}};
|
||||||
|
const ivec2* unbounded_const_arr = bounded_const_arr;
|
||||||
|
|
||||||
|
{
|
||||||
|
const meta::function func1 = ivec2_type.get_function("arg_bounded_arr");
|
||||||
|
REQUIRE(func1);
|
||||||
|
|
||||||
|
CHECK(func1.is_invocable_with<ivec2*>());
|
||||||
|
CHECK(func1.is_invocable_with<ivec2* const>());
|
||||||
|
CHECK_FALSE(func1.is_invocable_with<const ivec2*>());
|
||||||
|
CHECK_FALSE(func1.is_invocable_with<const ivec2* const>());
|
||||||
|
|
||||||
|
CHECK(func1.invoke(bounded_arr) == 10);
|
||||||
|
CHECK(func1.invoke(unbounded_arr) == 10);
|
||||||
|
CHECK_THROWS(func1.invoke(bounded_const_arr));
|
||||||
|
CHECK_THROWS(func1.invoke(unbounded_const_arr));
|
||||||
|
|
||||||
|
CHECK(func1.invoke(meta::value{bounded_arr}) == 10);
|
||||||
|
CHECK(func1.invoke(meta::value{unbounded_arr}) == 10);
|
||||||
|
CHECK_THROWS(func1.invoke(meta::value{bounded_const_arr}));
|
||||||
|
CHECK_THROWS(func1.invoke(meta::value{unbounded_const_arr}));
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_arr), decltype(bounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_arr), decltype(unbounded_arr)>);
|
||||||
|
static_assert(!std::is_invocable_v<decltype(&ivec2::arg_bounded_arr), decltype(bounded_const_arr)>);
|
||||||
|
static_assert(!std::is_invocable_v<decltype(&ivec2::arg_bounded_arr), decltype(unbounded_const_arr)>);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const meta::function func2 = ivec2_type.get_function("arg_unbounded_arr");
|
||||||
|
REQUIRE(func2);
|
||||||
|
|
||||||
|
CHECK(func2.is_invocable_with<ivec2*>());
|
||||||
|
CHECK(func2.is_invocable_with<ivec2* const>());
|
||||||
|
CHECK_FALSE(func2.is_invocable_with<const ivec2*>());
|
||||||
|
CHECK_FALSE(func2.is_invocable_with<const ivec2* const>());
|
||||||
|
|
||||||
|
CHECK(func2.invoke(bounded_arr) == 10);
|
||||||
|
CHECK(func2.invoke(unbounded_arr) == 10);
|
||||||
|
CHECK_THROWS(func2.invoke(bounded_const_arr));
|
||||||
|
CHECK_THROWS(func2.invoke(unbounded_const_arr));
|
||||||
|
|
||||||
|
CHECK(func2.invoke(meta::value{bounded_arr}) == 10);
|
||||||
|
CHECK(func2.invoke(meta::value{unbounded_arr}) == 10);
|
||||||
|
CHECK_THROWS(func2.invoke(meta::value{bounded_const_arr}));
|
||||||
|
CHECK_THROWS(func2.invoke(meta::value{unbounded_const_arr}));
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_arr), decltype(bounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_arr), decltype(unbounded_arr)>);
|
||||||
|
static_assert(!std::is_invocable_v<decltype(&ivec2::arg_unbounded_arr), decltype(bounded_const_arr)>);
|
||||||
|
static_assert(!std::is_invocable_v<decltype(&ivec2::arg_unbounded_arr), decltype(unbounded_const_arr)>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_const_arr") {
|
||||||
|
ivec2 bounded_arr[2]{{1,2},{3,4}};
|
||||||
|
ivec2* unbounded_arr = bounded_arr;
|
||||||
|
|
||||||
|
const ivec2 bounded_const_arr[2]{{1,2},{3,4}};
|
||||||
|
const ivec2* unbounded_const_arr = bounded_const_arr;
|
||||||
|
|
||||||
|
{
|
||||||
|
const meta::function func1 = ivec2_type.get_function("arg_bounded_const_arr");
|
||||||
|
REQUIRE(func1);
|
||||||
|
|
||||||
|
CHECK(func1.is_invocable_with<ivec2*>());
|
||||||
|
CHECK(func1.is_invocable_with<ivec2* const>());
|
||||||
|
CHECK(func1.is_invocable_with<const ivec2*>());
|
||||||
|
CHECK(func1.is_invocable_with<const ivec2* const>());
|
||||||
|
|
||||||
|
CHECK(func1.invoke(bounded_arr) == 10);
|
||||||
|
CHECK(func1.invoke(unbounded_arr) == 10);
|
||||||
|
CHECK(func1.invoke(bounded_const_arr) == 10);
|
||||||
|
CHECK(func1.invoke(unbounded_const_arr) == 10);
|
||||||
|
|
||||||
|
CHECK(func1.invoke(meta::value{bounded_arr}) == 10);
|
||||||
|
CHECK(func1.invoke(meta::value{unbounded_arr}) == 10);
|
||||||
|
CHECK(func1.invoke(meta::value{bounded_const_arr}) == 10);
|
||||||
|
CHECK(func1.invoke(meta::value{unbounded_const_arr}) == 10);
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_const_arr), decltype(bounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_const_arr), decltype(unbounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_const_arr), decltype(bounded_const_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_bounded_const_arr), decltype(unbounded_const_arr)>);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const meta::function func2 = ivec2_type.get_function("arg_unbounded_const_arr");
|
||||||
|
REQUIRE(func2);
|
||||||
|
|
||||||
|
CHECK(func2.is_invocable_with<ivec2*>());
|
||||||
|
CHECK(func2.is_invocable_with<ivec2* const>());
|
||||||
|
CHECK(func2.is_invocable_with<const ivec2*>());
|
||||||
|
CHECK(func2.is_invocable_with<const ivec2* const>());
|
||||||
|
|
||||||
|
CHECK(func2.invoke(bounded_arr) == 10);
|
||||||
|
CHECK(func2.invoke(unbounded_arr) == 10);
|
||||||
|
CHECK(func2.invoke(bounded_const_arr) == 10);
|
||||||
|
CHECK(func2.invoke(unbounded_const_arr) == 10);
|
||||||
|
|
||||||
|
CHECK(func2.invoke(meta::value{bounded_arr}) == 10);
|
||||||
|
CHECK(func2.invoke(meta::value{unbounded_arr}) == 10);
|
||||||
|
CHECK(func2.invoke(meta::value{bounded_const_arr}) == 10);
|
||||||
|
CHECK(func2.invoke(meta::value{unbounded_const_arr}) == 10);
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_const_arr), decltype(bounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_const_arr), decltype(unbounded_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_const_arr), decltype(bounded_const_arr)>);
|
||||||
|
static_assert(std::is_invocable_v<decltype(&ivec2::arg_unbounded_const_arr), decltype(unbounded_const_arr)>);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ namespace
|
|||||||
void arg_copy(ivec2) {}
|
void arg_copy(ivec2) {}
|
||||||
void arg_ref_noexcept(ivec2&) noexcept {}
|
void arg_ref_noexcept(ivec2&) noexcept {}
|
||||||
void arg_cref_noexcept(const ivec2&) noexcept {}
|
void arg_cref_noexcept(const ivec2&) noexcept {}
|
||||||
|
|
||||||
|
void arg_bounded_arr(ivec2[2]) {}
|
||||||
|
void arg_unbounded_arr(ivec2[]) {}
|
||||||
|
void arg_bounded_const_arr(const ivec2[2]) {}
|
||||||
|
void arg_unbounded_const_arr(const ivec2[]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("meta/meta_types/function_type") {
|
TEST_CASE("meta/meta_types/function_type") {
|
||||||
@@ -65,4 +70,52 @@ TEST_CASE("meta/meta_types/function_type") {
|
|||||||
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2&>());
|
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2&>());
|
||||||
CHECK_FALSE(type.get_argument_type(1));
|
CHECK_FALSE(type.get_argument_type(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_bounded_arr") {
|
||||||
|
const meta::function_type type = meta::resolve_type(&arg_bounded_arr);
|
||||||
|
REQUIRE(type);
|
||||||
|
|
||||||
|
CHECK(type.get_id() == meta::resolve_type(&arg_bounded_arr).get_id());
|
||||||
|
CHECK(type.get_flags() == meta::function_flags{});
|
||||||
|
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<ivec2*>()});
|
||||||
|
|
||||||
|
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2*>());
|
||||||
|
CHECK_FALSE(type.get_argument_type(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_unbounded_arr") {
|
||||||
|
const meta::function_type type = meta::resolve_type(&arg_unbounded_arr);
|
||||||
|
REQUIRE(type);
|
||||||
|
|
||||||
|
CHECK(type.get_id() == meta::resolve_type(&arg_unbounded_arr).get_id());
|
||||||
|
CHECK(type.get_flags() == meta::function_flags{});
|
||||||
|
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<ivec2*>()});
|
||||||
|
|
||||||
|
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2*>());
|
||||||
|
CHECK_FALSE(type.get_argument_type(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_bounded_const_arr") {
|
||||||
|
const meta::function_type type = meta::resolve_type(&arg_bounded_const_arr);
|
||||||
|
REQUIRE(type);
|
||||||
|
|
||||||
|
CHECK(type.get_id() == meta::resolve_type(&arg_bounded_const_arr).get_id());
|
||||||
|
CHECK(type.get_flags() == meta::function_flags{});
|
||||||
|
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<const ivec2*>()});
|
||||||
|
|
||||||
|
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2*>());
|
||||||
|
CHECK_FALSE(type.get_argument_type(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("arg_unbounded_const_arr") {
|
||||||
|
const meta::function_type type = meta::resolve_type(&arg_unbounded_const_arr);
|
||||||
|
REQUIRE(type);
|
||||||
|
|
||||||
|
CHECK(type.get_id() == meta::resolve_type(&arg_unbounded_const_arr).get_id());
|
||||||
|
CHECK(type.get_flags() == meta::function_flags{});
|
||||||
|
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<const ivec2*>()});
|
||||||
|
|
||||||
|
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2*>());
|
||||||
|
CHECK_FALSE(type.get_argument_type(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
254
untests/meta_utilities/arg5_tests.cpp
Normal file
254
untests/meta_utilities/arg5_tests.cpp
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* 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/arg5") {
|
||||||
|
namespace meta = meta_hpp;
|
||||||
|
|
||||||
|
// * <- B <- *
|
||||||
|
// A D
|
||||||
|
// * <- C <- *
|
||||||
|
|
||||||
|
meta::class_<A>();
|
||||||
|
meta::class_<B>().base_<A>();
|
||||||
|
meta::class_<C>().base_<A>();
|
||||||
|
meta::class_<D>().base_<B>().base_<C>();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("meta/meta_utilities/arg5/cast") {
|
||||||
|
namespace meta = meta_hpp;
|
||||||
|
using meta::detail::arg;
|
||||||
|
|
||||||
|
SUBCASE("int[2]") {
|
||||||
|
int arr[2]{1,2};
|
||||||
|
CHECK(arg(arr).get_raw_type() == meta::resolve_type(arr));
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<void(int*), int (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const int*), int (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(int* const), int (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const int* const), int (&) [2]>);
|
||||||
|
|
||||||
|
CHECK(arg(arr).can_cast_to<int*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const int*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<int* const>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const int* const>());
|
||||||
|
|
||||||
|
CHECK(arg(arr).cast<int*>() == static_cast<int*>(arr));
|
||||||
|
CHECK(arg(arr).cast<const int*>() == static_cast<const int*>(arr));
|
||||||
|
CHECK(arg(arr).cast<int* const>() == static_cast<int*>(arr));
|
||||||
|
CHECK(arg(arr).cast<const int* const>() == static_cast<const int*>(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("const int[2]") {
|
||||||
|
const int arr[2]{1,2};
|
||||||
|
CHECK(arg(arr).get_raw_type() == meta::resolve_type(arr));
|
||||||
|
|
||||||
|
static_assert(!std::is_invocable_v<void(int*), const int (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const int*), const int (&) [2]>);
|
||||||
|
static_assert(!std::is_invocable_v<void(int* const), const int (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const int* const), const int (&) [2]>);
|
||||||
|
|
||||||
|
CHECK_FALSE(arg(arr).can_cast_to<int*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const int*>());
|
||||||
|
CHECK_FALSE(arg(arr).can_cast_to<int* const>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const int* const>());
|
||||||
|
|
||||||
|
CHECK_THROWS(std::ignore = arg(arr).cast<int*>());
|
||||||
|
CHECK(arg(arr).cast<const int*>() == static_cast<const int*>(arr));
|
||||||
|
CHECK_THROWS(std::ignore = arg(arr).cast<int* const>());
|
||||||
|
CHECK(arg(arr).cast<const int* const>() == static_cast<const int*>(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("D[2]") {
|
||||||
|
D arr[2];
|
||||||
|
CHECK(arg(arr).get_raw_type() == meta::resolve_type(arr));
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<void(A*), D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(A* const), D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), D (&) [2]>);
|
||||||
|
|
||||||
|
CHECK(arg(arr).can_cast_to<A*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const A*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<A* const>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const A* const>());
|
||||||
|
|
||||||
|
CHECK(arg(arr).cast<A*>() == static_cast<A*>(arr));
|
||||||
|
CHECK(arg(arr).cast<const A*>() == static_cast<const A*>(arr));
|
||||||
|
CHECK(arg(arr).cast<A* const>() == static_cast<A*>(arr));
|
||||||
|
CHECK(arg(arr).cast<const A* const>() == static_cast<const A*>(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("const D[2]") {
|
||||||
|
const D arr[2];
|
||||||
|
CHECK(arg(arr).get_raw_type() == meta::resolve_type(arr));
|
||||||
|
|
||||||
|
static_assert(!std::is_invocable_v<void(A*), const D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), const D (&) [2]>);
|
||||||
|
static_assert(!std::is_invocable_v<void(A* const), const D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), const D (&) [2]>);
|
||||||
|
|
||||||
|
CHECK_FALSE(arg(arr).can_cast_to<A*>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const A*>());
|
||||||
|
CHECK_FALSE(arg(arr).can_cast_to<A* const>());
|
||||||
|
CHECK(arg(arr).can_cast_to<const A* const>());
|
||||||
|
|
||||||
|
CHECK_THROWS(std::ignore = arg(arr).cast<A*>());
|
||||||
|
CHECK(arg(arr).cast<const A*>() == static_cast<const A*>(arr));
|
||||||
|
CHECK_THROWS(std::ignore = arg(arr).cast<A* const>());
|
||||||
|
CHECK(arg(arr).cast<const A* const>() == static_cast<const A*>(arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("&") {
|
||||||
|
using T = D[2];
|
||||||
|
static T src{};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto LV = []() -> T& { return src; };
|
||||||
|
CHECK(arg{LV()}.get_raw_type() == meta::resolve_type<D[2]>());
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<void(A*), decltype(LV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), decltype(LV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(A* const), decltype(LV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), decltype(LV())>);
|
||||||
|
|
||||||
|
CHECK_NOTHROW([](A*){}(LV()));
|
||||||
|
CHECK_NOTHROW([](const A*){}(LV()));
|
||||||
|
CHECK_NOTHROW([](A* const){}(LV()));
|
||||||
|
CHECK_NOTHROW([](const A* const){}(LV()));
|
||||||
|
|
||||||
|
CHECK(arg(LV()).cast<A*>() == static_cast<A*>(src));
|
||||||
|
CHECK(arg(LV()).cast<const A*>() == static_cast<const A*>(src));
|
||||||
|
CHECK(arg(LV()).cast<A* const>() == static_cast<A*>(src));
|
||||||
|
CHECK(arg(LV()).cast<const A* const>() == static_cast<const A*>(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto CLV = []() -> const T& { return src; };
|
||||||
|
CHECK(arg{CLV()}.get_raw_type() == meta::resolve_type<D[2]>());
|
||||||
|
|
||||||
|
static_assert(!std::is_invocable_v<void(A*), decltype(CLV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), decltype(CLV())>);
|
||||||
|
static_assert(!std::is_invocable_v<void(A* const), decltype(CLV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), decltype(CLV())>);
|
||||||
|
|
||||||
|
CHECK_THROWS(std::ignore = arg(CLV()).cast<A*>());
|
||||||
|
CHECK(arg(CLV()).cast<const A*>() == static_cast<const A*>(src));
|
||||||
|
CHECK_THROWS(std::ignore = arg(CLV()).cast<A* const>());
|
||||||
|
CHECK(arg(CLV()).cast<const A* const>() == static_cast<const A*>(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto XV = []() -> T&& { return std::move(src); };
|
||||||
|
CHECK(arg{XV()}.get_raw_type() == meta::resolve_type<D[2]>());
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<void(A*), decltype(XV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), decltype(XV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(A* const), decltype(XV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), decltype(XV())>);
|
||||||
|
|
||||||
|
CHECK(arg(XV()).cast<A*>() == static_cast<A*>(src));
|
||||||
|
CHECK(arg(XV()).cast<const A*>() == static_cast<const A*>(src));
|
||||||
|
CHECK(arg(XV()).cast<A* const>() == static_cast<A*>(src));
|
||||||
|
CHECK(arg(XV()).cast<const A* const>() == static_cast<const A*>(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto CXV = []() -> const T&& { return std::move(src); };
|
||||||
|
CHECK(arg{CXV()}.get_raw_type() == meta::resolve_type<D[2]>());
|
||||||
|
|
||||||
|
static_assert(!std::is_invocable_v<void(A*), decltype(CXV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A*), decltype(CXV())>);
|
||||||
|
static_assert(!std::is_invocable_v<void(A* const), decltype(CXV())>);
|
||||||
|
static_assert(std::is_invocable_v<void(const A* const), decltype(CXV())>);
|
||||||
|
|
||||||
|
CHECK_THROWS(std::ignore = arg(CXV()).cast<A*>());
|
||||||
|
CHECK(arg(CXV()).cast<const A*>() == static_cast<const A*>(src));
|
||||||
|
CHECK_THROWS(std::ignore = arg(CXV()).cast<A* const>());
|
||||||
|
CHECK(arg(CXV()).cast<const A* const>() == static_cast<const A*>(src));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("*") {
|
||||||
|
{
|
||||||
|
static D arr[2]{};
|
||||||
|
|
||||||
|
static_assert(std::is_invocable_v<void(D (&) [2]), D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (&) [2]), D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(D (*) [2]), D (*) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (*) [2]), D (*) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(D (* const) [2]), D (*) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (* const) [2]), D (*) [2]>);
|
||||||
|
|
||||||
|
CHECK(arg{arr}.can_cast_to<D (&) [2]>());
|
||||||
|
CHECK(arg{arr}.can_cast_to<const D (&) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<D (*) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<const D (*) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<D (* const) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<const D (* const) [2]>());
|
||||||
|
|
||||||
|
CHECK(&arg{arr}.cast<D (&) [2]>() == &arr);
|
||||||
|
CHECK(&arg{arr}.cast<const D (&) [2]>() == &arr);
|
||||||
|
CHECK(arg{&arr}.cast<D (*) [2]>() == &arr);
|
||||||
|
CHECK(arg{&arr}.cast<const D (*) [2]>() == &arr);
|
||||||
|
CHECK(arg{&arr}.cast<D (* const) [2]>() == &arr);
|
||||||
|
CHECK(arg{&arr}.cast<const D (* const) [2]>() == &arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static const D arr[2]{};
|
||||||
|
|
||||||
|
static_assert(!std::is_invocable_v<void(D (&) [2]), const D (&) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (&) [2]), const D (&) [2]>);
|
||||||
|
static_assert(!std::is_invocable_v<void(D (*) [2]), const D (*) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (*) [2]), const D (*) [2]>);
|
||||||
|
static_assert(!std::is_invocable_v<void(D (* const) [2]), const D (*) [2]>);
|
||||||
|
static_assert(std::is_invocable_v<void(const D (* const) [2]), const D (*) [2]>);
|
||||||
|
|
||||||
|
CHECK_FALSE(arg{arr}.can_cast_to<D (&) [2]>());
|
||||||
|
CHECK(arg{arr}.can_cast_to<const D (&) [2]>());
|
||||||
|
CHECK_FALSE(arg{&arr}.can_cast_to<D (*) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<const D (*) [2]>());
|
||||||
|
CHECK_FALSE(arg{&arr}.can_cast_to<D (* const) [2]>());
|
||||||
|
CHECK(arg{&arr}.can_cast_to<const D (* const) [2]>());
|
||||||
|
|
||||||
|
CHECK_THROWS(std::ignore = &arg{arr}.cast<D (&) [2]>());
|
||||||
|
CHECK(&arg{arr}.cast<const D (&) [2]>() == &arr);
|
||||||
|
CHECK_THROWS(std::ignore = arg{&arr}.cast<D (*) [2]>());
|
||||||
|
CHECK(arg{&arr}.cast<const D (*) [2]>() == &arr);
|
||||||
|
CHECK_THROWS(std::ignore = arg{&arr}.cast<D (* const) [2]>());
|
||||||
|
CHECK(arg{&arr}.cast<const D (* const) [2]>() == &arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user