hide all developer stuff to develop directory

This commit is contained in:
BlackMATov
2023-01-09 16:06:46 +07:00
parent 6922c2019b
commit 615be2345d
74 changed files with 37 additions and 45 deletions

View File

@@ -0,0 +1,18 @@
---
Checks: '-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
clang-analyzer-*,
concurrency-*,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
portability-*,
'
...

View File

@@ -0,0 +1,80 @@
project(meta.hpp.untests)
file(GLOB_RECURSE UNTESTS_SOURCES "*.cpp" "*.hpp")
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${UNTESTS_SOURCES})
add_executable(${PROJECT_NAME} ${UNTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp::meta.hpp)
add_executable(${PROJECT_NAME}.singles ${UNTESTS_SOURCES})
target_link_libraries(${PROJECT_NAME}.singles PRIVATE meta.hpp::singles)
#
# setup defines
#
function(setup_defines_for_target TARGET)
target_compile_definitions(${TARGET} PRIVATE
DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
DOCTEST_CONFIG_USE_STD_HEADERS)
endfunction()
setup_defines_for_target(${PROJECT_NAME})
setup_defines_for_target(${PROJECT_NAME}.singles)
#
# setup libraries
#
function(setup_libraries_for_target TARGET)
target_link_libraries(${TARGET} PRIVATE doctest::doctest_with_main)
if(BUILD_WITH_COVERAGE)
target_link_libraries(${TARGET} PRIVATE meta.hpp::enable_gcov)
endif()
if(BUILD_WITH_SANITIZERS)
target_link_libraries(${TARGET} PRIVATE meta.hpp::enable_asan meta.hpp::enable_ubsan)
endif()
endfunction()
setup_libraries_for_target(${PROJECT_NAME})
setup_libraries_for_target(${PROJECT_NAME}.singles)
#
# setup warnings
#
function(setup_warnings_for_target TARGET)
target_compile_options(${TARGET}
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:
/WX /W4>
PRIVATE
$<$<CXX_COMPILER_ID:GNU>:
-Werror -Wall -Wextra -Wpedantic>
PRIVATE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
-Werror -Weverything -Wconversion
-Wno-c++98-compat
-Wno-c++98-compat-pedantic
-Wno-exit-time-destructors
-Wno-global-constructors
-Wno-padded
-Wno-unknown-warning-option
-Wno-unneeded-internal-declaration
-Wno-unneeded-member-function
-Wno-unused-macros
-Wno-weak-vtables
>)
endfunction()
setup_warnings_for_target(${PROJECT_NAME})
setup_warnings_for_target(${PROJECT_NAME}.singles)
#
# add tests
#
add_test(${PROJECT_NAME} ${PROJECT_NAME})
add_test(${PROJECT_NAME} ${PROJECT_NAME}.singles)

View File

@@ -0,0 +1,127 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_base/fixed_function") {
namespace meta = meta_hpp;
using meta::detail::fixed_function;
SUBCASE("is_valid") {
{
fixed_function<void()> ff;
CHECK_FALSE(ff);
CHECK_FALSE(ff.is_valid());
}
{
fixed_function<void()> ff = []{};
CHECK(ff);
CHECK(ff.is_valid());
}
}
SUBCASE("ctor") {
{
auto f1 = []{return 1;};
fixed_function<int()> ff{std::move(f1)};
CHECK(ff() == 1);
auto f2 = fixed_function{[]{return 2;}};
ff = std::move(f2);
CHECK(ff() == 2);
}
{
auto f1 = []() noexcept {return 1;};
fixed_function ff{f1};
CHECK(ff() == 1);
}
}
SUBCASE("reset") {
fixed_function ff = []{return 0;};
ff.reset();
CHECK_FALSE(ff);
CHECK_FALSE(ff.is_valid());
ff = []{return 1;};
CHECK(ff);
CHECK(ff.is_valid());
CHECK(ff() == 1);
}
SUBCASE("move") {
fixed_function ff = []{return 1;};
fixed_function ff2 = std::move(ff);
CHECK(ff2() == 1);
CHECK_FALSE(ff);
}
SUBCASE("operator=") {
{
fixed_function<int()> ff;
ff = []{return 0;};
CHECK(ff() == 0);
ff = []{return 1;};
CHECK(ff() == 1);
fixed_function<int()> ff2 = []{return 2;};
ff = std::move(ff2);
CHECK(ff() == 2);
CHECK_FALSE(ff2);
}
}
SUBCASE("swap") {
{
fixed_function<void()> ff1;
fixed_function<void()> ff2;
ff1.swap(ff2);
CHECK_FALSE(ff1);
CHECK_FALSE(ff2);
}
{
fixed_function ff1 = []{return 1;};
fixed_function ff2 = []{return 2;};
ff1.swap(ff2);
CHECK(ff1() == 2);
CHECK(ff2() == 1);
}
{
fixed_function<int()> ff1;
fixed_function ff2 = []{return 2;};
ff1.swap(ff2);
CHECK(ff1() == 2);
CHECK_FALSE(ff2);
ff1.swap(ff2);
CHECK_FALSE(ff1);
CHECK(ff2() == 2);
}
}
SUBCASE("-> int") {
auto f = [
s = std::make_unique<int>(10)
](){ return 0; };
fixed_function ff = std::move(f);
CHECK(ff() == 0);
}
SUBCASE("-> void") {
auto f = [
s = std::make_unique<int>(10)
](){};
fixed_function ff = std::move(f);
CHECK_NOTHROW(ff());
}
}

View File

@@ -0,0 +1,171 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_base/memory_buffer") {
namespace meta = meta_hpp;
using meta::detail::memory_buffer;
SUBCASE("ctor/0") {
memory_buffer buf;
CHECK(!buf);
CHECK(!buf.is_valid());
CHECK(buf.get_size() == 0);
CHECK(buf.get_align() == std::align_val_t{});
CHECK(buf.get_memory() == nullptr);
CHECK(std::as_const(buf).get_memory() == nullptr);
}
SUBCASE("ctor/1") {
memory_buffer buf1{10, std::align_val_t{32}};
const void* buf1_memory{buf1.get_memory()};
memory_buffer buf2{std::move(buf1)};
{
CHECK(!buf1);
CHECK(!buf1.is_valid());
CHECK(buf1.get_size() == 0);
CHECK(buf1.get_align() == std::align_val_t{});
CHECK(buf1.get_memory() == nullptr);
CHECK(std::as_const(buf1).get_memory() == nullptr);
}
{
CHECK(buf2);
CHECK(buf2.is_valid());
CHECK(buf2.get_size() == 10);
CHECK(buf2.get_align() == std::align_val_t{32});
CHECK(buf2.get_memory() == buf1_memory);
CHECK(std::as_const(buf2).get_memory() == buf1_memory);
}
}
SUBCASE("ctor/2") {
memory_buffer buf{10, std::align_val_t{32}};
CHECK(buf);
CHECK(buf.is_valid());
CHECK(buf.get_size() == 10);
CHECK(buf.get_align() == std::align_val_t{32});
CHECK(buf.get_memory());
CHECK(std::as_const(buf).get_memory());
{
void* aligned_ptr{buf.get_memory()};
std::size_t aligned_size{buf.get_size()};
CHECK(std::align(
meta::detail::to_underlying(buf.get_align()), buf.get_size(),
aligned_ptr, aligned_size) == buf.get_memory());
}
}
SUBCASE("operator=/0") {
memory_buffer buf1{10, std::align_val_t{32}};
const void* buf1_memory{buf1.get_memory()};
memory_buffer buf2;
buf2 = std::move(buf1);
{
CHECK(!buf1);
CHECK(!buf1.is_valid());
CHECK(buf1.get_size() == 0);
CHECK(buf1.get_align() == std::align_val_t{});
CHECK(buf1.get_memory() == nullptr);
CHECK(std::as_const(buf1).get_memory() == nullptr);
}
{
CHECK(buf2);
CHECK(buf2.is_valid());
CHECK(buf2.get_size() == 10);
CHECK(buf2.get_align() == std::align_val_t{32});
CHECK(buf2.get_memory() == buf1_memory);
CHECK(std::as_const(buf2).get_memory() == buf1_memory);
}
}
SUBCASE("operator=/1") {
memory_buffer buf1{10, std::align_val_t{32}};
const void* buf1_memory{buf1.get_memory()};
memory_buffer buf2{20, std::align_val_t{16}};
buf2 = std::move(buf1);
{
CHECK(!buf1);
CHECK(!buf1.is_valid());
CHECK(buf1.get_size() == 0);
CHECK(buf1.get_align() == std::align_val_t{});
CHECK(buf1.get_memory() == nullptr);
CHECK(std::as_const(buf1).get_memory() == nullptr);
}
{
CHECK(buf2);
CHECK(buf2.is_valid());
CHECK(buf2.get_size() == 10);
CHECK(buf2.get_align() == std::align_val_t{32});
CHECK(buf2.get_memory() == buf1_memory);
CHECK(std::as_const(buf2).get_memory() == buf1_memory);
}
}
SUBCASE("reset") {
memory_buffer buf{10, std::align_val_t{32}};
buf.reset();
CHECK(!buf);
CHECK(!buf.is_valid());
CHECK(buf.get_size() == 0);
CHECK(buf.get_align() == std::align_val_t{});
CHECK(buf.get_memory() == nullptr);
CHECK(std::as_const(buf).get_memory() == nullptr);
}
SUBCASE("swap") {
memory_buffer buf1{10, std::align_val_t{32}};
memory_buffer buf2{15, std::align_val_t{16}};
const void* buf1_memory{buf1.get_memory()};
const void* buf2_memory{buf2.get_memory()};
meta::detail::swap(buf1, buf2);
CHECK(buf1.get_size() == 15);
CHECK(buf1.get_align() == std::align_val_t{16});
CHECK(buf1.get_memory() == buf2_memory);
CHECK(buf2.get_size() == 10);
CHECK(buf2.get_align() == std::align_val_t{32});
CHECK(buf2.get_memory() == buf1_memory);
}
}

View File

@@ -0,0 +1,338 @@
/*******************************************************************************
* 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;
[[maybe_unused]] A(A&&) = default;
[[maybe_unused]]A(const A&) = default;
A& operator=(A&&) = delete;
A& operator=(const A&) = delete;
virtual ~A() = default;
};
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
struct E {};
}
TEST_CASE("meta/meta_features/diamond") {
namespace meta = meta_hpp;
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
meta::class_<E>();
// * <- B <- *
// A D
// * <- C <- *
const meta::class_type A_type = meta::resolve_type<A>();
const meta::class_type B_type = meta::resolve_type<B>();
const meta::class_type C_type = meta::resolve_type<C>();
const meta::class_type D_type = meta::resolve_type<D>();
const meta::class_type E_type = meta::resolve_type<E>();
REQUIRE(A_type);
REQUIRE(B_type);
REQUIRE(C_type);
REQUIRE(D_type);
REQUIRE(E_type);
SUBCASE("is_base_of") {
CHECK(!A_type.is_base_of(A_type));
CHECK(A_type.is_base_of(B_type));
CHECK(A_type.is_base_of(C_type));
CHECK(A_type.is_base_of(D_type));
CHECK(!A_type.is_base_of(E_type));
CHECK(!B_type.is_base_of(A_type));
CHECK(!B_type.is_base_of(B_type));
CHECK(!B_type.is_base_of(C_type));
CHECK(B_type.is_base_of(D_type));
CHECK(!B_type.is_base_of(E_type));
CHECK(!C_type.is_base_of(A_type));
CHECK(!C_type.is_base_of(B_type));
CHECK(!C_type.is_base_of(C_type));
CHECK(C_type.is_base_of(D_type));
CHECK(!C_type.is_base_of(E_type));
CHECK(!D_type.is_base_of(A_type));
CHECK(!D_type.is_base_of(B_type));
CHECK(!D_type.is_base_of(C_type));
CHECK(!D_type.is_base_of(D_type));
CHECK(!D_type.is_base_of(E_type));
CHECK(!E_type.is_base_of(A_type));
CHECK(!E_type.is_base_of(B_type));
CHECK(!E_type.is_base_of(C_type));
CHECK(!E_type.is_base_of(D_type));
CHECK(!E_type.is_base_of(E_type));
}
SUBCASE("is_derived_from") {
CHECK(!A_type.is_derived_from(A_type));
CHECK(!A_type.is_derived_from(B_type));
CHECK(!A_type.is_derived_from(C_type));
CHECK(!A_type.is_derived_from(D_type));
CHECK(!A_type.is_derived_from(E_type));
CHECK(B_type.is_derived_from(A_type));
CHECK(!B_type.is_derived_from(B_type));
CHECK(!B_type.is_derived_from(C_type));
CHECK(!B_type.is_derived_from(D_type));
CHECK(!B_type.is_derived_from(E_type));
CHECK(C_type.is_derived_from(A_type));
CHECK(!C_type.is_derived_from(B_type));
CHECK(!C_type.is_derived_from(C_type));
CHECK(!C_type.is_derived_from(D_type));
CHECK(!C_type.is_derived_from(E_type));
CHECK(D_type.is_derived_from(A_type));
CHECK(D_type.is_derived_from(B_type));
CHECK(D_type.is_derived_from(C_type));
CHECK(!D_type.is_derived_from(D_type));
CHECK(!D_type.is_derived_from(E_type));
CHECK(!E_type.is_derived_from(A_type));
CHECK(!E_type.is_derived_from(B_type));
CHECK(!E_type.is_derived_from(C_type));
CHECK(!E_type.is_derived_from(D_type));
CHECK(!E_type.is_derived_from(E_type));
}
SUBCASE("pointer_upcast") {
using meta::detail::pointer_upcast;
{
A a;
CHECK(pointer_upcast<A>(&a) == &a);
CHECK_FALSE(pointer_upcast<B>(&a));
CHECK_FALSE(pointer_upcast<C>(&a));
CHECK_FALSE(pointer_upcast<D>(&a));
CHECK_FALSE(pointer_upcast<E>(&a));
}
{
const B b;
CHECK(pointer_upcast<A>(&b) == &b);
CHECK(pointer_upcast<B>(&b) == &b);
CHECK_FALSE(pointer_upcast<C>(&b));
CHECK_FALSE(pointer_upcast<D>(&b));
CHECK_FALSE(pointer_upcast<E>(&b));
}
{
C c;
CHECK(pointer_upcast<A>(&c) == &c);
CHECK_FALSE(pointer_upcast<B>(&c));
CHECK(pointer_upcast<C>(&c) == &c);
CHECK_FALSE(pointer_upcast<D>(&c));
CHECK_FALSE(pointer_upcast<E>(&c));
}
{
const D d;
CHECK(pointer_upcast<A>(&d) == &d);
CHECK(pointer_upcast<B>(&d) == &d);
CHECK(pointer_upcast<C>(&d) == &d);
CHECK(pointer_upcast<D>(&d) == &d);
CHECK_FALSE(pointer_upcast<E>(&d));
}
{
E e;
CHECK_FALSE(pointer_upcast<A>(&e));
CHECK_FALSE(pointer_upcast<B>(&e));
CHECK_FALSE(pointer_upcast<C>(&e));
CHECK_FALSE(pointer_upcast<D>(&e));
CHECK(pointer_upcast<E>(&e) == &e);
}
}
SUBCASE("arg/cast") {
{
A a;
meta::uvalue a_val{&a};
CHECK(*static_cast<A**>(a_val.data()) == &a);
meta::detail::uarg a_arg{a_val};
CHECK(a_arg.can_cast_to<A*>());
CHECK(!a_arg.can_cast_to<B*>());
CHECK(!a_arg.can_cast_to<C*>());
CHECK(!a_arg.can_cast_to<D*>());
CHECK(!a_arg.can_cast_to<E*>());
CHECK(a_arg.cast<A*>() == static_cast<A*>(&a));
}
{
B b;
meta::uvalue b_val{&b};
CHECK(*static_cast<B**>(b_val.data()) == &b);
meta::detail::uarg b_arg{b_val};
CHECK(b_arg.can_cast_to<A*>());
CHECK(b_arg.can_cast_to<B*>());
CHECK(!b_arg.can_cast_to<C*>());
CHECK(!b_arg.can_cast_to<D*>());
CHECK(!b_arg.can_cast_to<E*>());
CHECK(b_arg.cast<A*>() == static_cast<A*>(&b));
CHECK(b_arg.cast<B*>() == static_cast<B*>(&b));
}
{
C c;
meta::uvalue c_val{&c};
CHECK(*static_cast<C**>(c_val.data()) == &c);
meta::detail::uarg c_arg{c_val};
CHECK(c_arg.can_cast_to<A*>());
CHECK(!c_arg.can_cast_to<B*>());
CHECK(c_arg.can_cast_to<C*>());
CHECK(!c_arg.can_cast_to<D*>());
CHECK(!c_arg.can_cast_to<E*>());
CHECK(c_arg.cast<A*>() == static_cast<A*>(&c));
CHECK(c_arg.cast<C*>() == static_cast<C*>(&c));
}
{
D d;
meta::uvalue d_val{&d};
CHECK(*static_cast<D**>(d_val.data()) == &d);
meta::detail::uarg d_arg{d_val};
CHECK(d_arg.can_cast_to<A*>());
CHECK(d_arg.can_cast_to<B*>());
CHECK(d_arg.can_cast_to<C*>());
CHECK(d_arg.can_cast_to<D*>());
CHECK(!d_arg.can_cast_to<E*>());
CHECK(d_arg.cast<A*>() == static_cast<A*>(&d));
CHECK(d_arg.cast<B*>() == static_cast<B*>(&d));
CHECK(d_arg.cast<C*>() == static_cast<C*>(&d));
CHECK(d_arg.cast<D*>() == static_cast<D*>(&d));
}
{
E e;
meta::uvalue e_val{&e};
CHECK(*static_cast<E**>(e_val.data()) == &e);
meta::detail::uarg e_arg{e_val};
CHECK(!e_arg.can_cast_to<A*>());
CHECK(!e_arg.can_cast_to<B*>());
CHECK(!e_arg.can_cast_to<C*>());
CHECK(!e_arg.can_cast_to<D*>());
CHECK(e_arg.can_cast_to<E*>());
CHECK(e_arg.cast<E*>() == static_cast<E*>(&e));
}
}
SUBCASE("inst/cast") {
{
meta::uvalue a_val{A{}};
meta::detail::uinst a_inst{a_val};
CHECK(a_inst.can_cast_to<A&>());
CHECK_FALSE(a_inst.can_cast_to<B&>());
CHECK_FALSE(a_inst.can_cast_to<C&>());
CHECK_FALSE(a_inst.can_cast_to<D&>());
CHECK_FALSE(a_inst.can_cast_to<E&>());
CHECK(&a_inst.cast<A&>() == &a_val.get_as<A>());
}
{
meta::uvalue b_val{B{}};
meta::detail::uinst b_inst{b_val};
CHECK(b_inst.can_cast_to<A&>());
CHECK(b_inst.can_cast_to<B&>());
CHECK_FALSE(b_inst.can_cast_to<C&>());
CHECK_FALSE(b_inst.can_cast_to<D&>());
CHECK_FALSE(b_inst.can_cast_to<E&>());
CHECK(&b_inst.cast<A&>() == &b_val.get_as<B>());
CHECK(&b_inst.cast<B&>() == &b_val.get_as<B>());
CHECK(&b_inst.cast<A&>() == &b_val.get_as<B>());
}
{
meta::uvalue c_val{C{}};
meta::detail::uinst c_inst{c_val};
CHECK(c_inst.can_cast_to<A&>());
CHECK_FALSE(c_inst.can_cast_to<B&>());
CHECK(c_inst.can_cast_to<C&>());
CHECK_FALSE(c_inst.can_cast_to<D&>());
CHECK_FALSE(c_inst.can_cast_to<E&>());
CHECK(&c_inst.cast<A&>() == &c_val.get_as<C>());
CHECK(&c_inst.cast<C&>() == &c_val.get_as<C>());
}
{
meta::uvalue d_val{D{}};
meta::detail::uinst d_inst{d_val};
CHECK(d_inst.can_cast_to<A&>());
CHECK(d_inst.can_cast_to<B&>());
CHECK(d_inst.can_cast_to<C&>());
CHECK(d_inst.can_cast_to<D&>());
CHECK_FALSE(d_inst.can_cast_to<E&>());
CHECK(&d_inst.cast<A&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<B&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<C&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<D&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<A&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<B&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<C&>() == &d_val.get_as<D>());
CHECK(&d_inst.cast<D&>() == &d_val.get_as<D>());
}
{
meta::uvalue e_val{E{}};
meta::detail::uinst e_inst{e_val};
CHECK_FALSE(e_inst.can_cast_to<A&>());
CHECK_FALSE(e_inst.can_cast_to<B&>());
CHECK_FALSE(e_inst.can_cast_to<C&>());
CHECK_FALSE(e_inst.can_cast_to<D&>());
CHECK(e_inst.can_cast_to<E&>());
CHECK(&e_inst.cast<E&>() == &e_val.get_as<E>());
}
}
SUBCASE("resolve_polymorphic_type") {
const D d;
const A& ad = d;
const B& bd = d;
const C& cd = d;
const D& dd = d;
CHECK(meta::resolve_type(ad) == meta::resolve_type<A>());
CHECK(meta::resolve_type(bd) == meta::resolve_type<B>());
CHECK(meta::resolve_type(cd) == meta::resolve_type<C>());
CHECK(meta::resolve_type(dd) == meta::resolve_type<D>());
CHECK(meta::resolve_polymorphic_type(ad) == meta::resolve_type<D>());
CHECK(meta::resolve_polymorphic_type(bd) == meta::resolve_type<D>());
CHECK(meta::resolve_polymorphic_type(cd) == meta::resolve_type<D>());
CHECK(meta::resolve_polymorphic_type(dd) == meta::resolve_type<D>());
}
}

View File

@@ -0,0 +1,38 @@
/*******************************************************************************
* 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
{
class rect {
public:
void get_width(int* v) {
*v = 42;
}
static void get_width_static(int* v) {
*v = 84;
}
};
}
TEST_CASE("meta/meta_issues/15") {
namespace meta = meta_hpp;
meta::class_<rect>()
.method_("get_width", &rect::get_width)
.function_("get_width_static", &rect::get_width_static);
int v{};
rect r{};
meta::resolve_type(r).get_method("get_width").invoke(r, &v);
CHECK(v == 42);
meta::resolve_type(r).get_function("get_width_static").invoke(&v);
CHECK(v == 84);
}

View File

@@ -0,0 +1,402 @@
/*******************************************************************************
* 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
{
template < typename Tag >
struct clazz {
int i{};
clazz(int ni) : i{ni} {
++constructor_counter;
}
clazz(clazz&& other) : i{other.i} {
other.i = 0;
++move_constructor_counter;
}
clazz(const clazz& other) : i{other.i} {
++copy_constructor_counter;
}
clazz& operator=(clazz&& other) = delete;
clazz& operator=(const clazz& other) = delete;
~clazz() {
++destructor_counter;
}
inline static int constructor_counter{};
inline static int destructor_counter{};
inline static int move_constructor_counter{};
inline static int copy_constructor_counter{};
};
template < typename Tag >
struct clazz_noncopyable {
int i{};
clazz_noncopyable(int ni) : i{ni} {
++constructor_counter;
}
clazz_noncopyable(clazz_noncopyable&& other) : i{other.i} {
other.i = 0;
++move_constructor_counter;
}
clazz_noncopyable(const clazz_noncopyable& other) = delete;
clazz_noncopyable& operator=(clazz_noncopyable&& other) = delete;
clazz_noncopyable& operator=(const clazz_noncopyable& other) = delete;
~clazz_noncopyable() {
++destructor_counter;
}
inline static int constructor_counter{};
inline static int destructor_counter{};
inline static int move_constructor_counter{};
inline static int copy_constructor_counter{};
};
}
TEST_CASE("meta/meta_states/ctor/noncopyable") {
namespace meta = meta_hpp;
using clazz_t = clazz_noncopyable<meta::constructor_policy::as_raw_pointer_t>;
meta::class_<clazz_t>()
.constructor_<int>(meta::constructor_policy::as_raw_pointer)
.constructor_<clazz_t&&>(meta::constructor_policy::as_raw_pointer);
clazz_t::constructor_counter = 0;
clazz_t::destructor_counter = 0;
clazz_t::move_constructor_counter = 0;
clazz_t::copy_constructor_counter = 0;
const meta::class_type clazz_type = meta::resolve_type<clazz_t>();
REQUIRE(clazz_type);
SUBCASE("int") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<int>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, int>());
}
{
const meta::uvalue v = clazz_type.create(42);
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
CHECK(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<clazz_t&&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, clazz_t&&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::move(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
CHECK(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
}
TEST_CASE("meta/meta_states/ctor/as_object") {
namespace meta = meta_hpp;
using clazz_t = clazz<meta::constructor_policy::as_object_t>;
meta::class_<clazz_t>()
.constructor_<int>(meta::constructor_policy::as_object)
.constructor_<clazz_t&&>(meta::constructor_policy::as_object)
.constructor_<const clazz_t&>(meta::constructor_policy::as_object);
clazz_t::constructor_counter = 0;
clazz_t::destructor_counter = 0;
clazz_t::move_constructor_counter = 0;
clazz_t::copy_constructor_counter = 0;
const meta::class_type clazz_type = meta::resolve_type<clazz_t>();
REQUIRE(clazz_type);
alignas(clazz_t) std::byte clazz_mem[sizeof(clazz_t)];
SUBCASE("int") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<int>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, int>());
}
{
const meta::uvalue v = clazz_type.create(42);
CHECK(v.get_type() == meta::resolve_type<clazz_t>());
CHECK(v.get_as<clazz_t>().i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("int/inplace") {
{
const meta::uvalue v = clazz_type
.get_constructor_with<int>()
.create_at(clazz_mem, 42);
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
clazz_type.get_destructor().destroy_at(clazz_mem);
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<clazz_t&&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, clazz_t&&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::move(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t>());
CHECK(v.get_as<clazz_t>().i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&/inplace") {
{
clazz_t o{42};
const meta::uvalue v = clazz_type
.get_constructor_with<clazz_t&&>()
.create_at(clazz_mem, std::move(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
clazz_type.get_destructor().destroy_at(clazz_mem);
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("const clazz_t&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<const clazz_t&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, const clazz_t&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::as_const(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t>());
CHECK(v.get_as<clazz_t>().i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 1);
}
SUBCASE("const clazz_t&/inplace") {
{
clazz_t o{42};
const meta::uvalue v = clazz_type
.get_constructor_with<const clazz_t&>()
.create_at(clazz_mem, std::as_const(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
clazz_type.get_destructor().destroy_at(clazz_mem);
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 1);
}
}
TEST_CASE("meta/meta_states/ctor/as_raw_pointer") {
namespace meta = meta_hpp;
using clazz_t = clazz<meta::constructor_policy::as_raw_pointer_t>;
meta::class_<clazz_t>()
.constructor_<int>(meta::constructor_policy::as_raw_pointer)
.constructor_<clazz_t&&>(meta::constructor_policy::as_raw_pointer)
.constructor_<const clazz_t&>(meta::constructor_policy::as_raw_pointer);
clazz_t::constructor_counter = 0;
clazz_t::destructor_counter = 0;
clazz_t::move_constructor_counter = 0;
clazz_t::copy_constructor_counter = 0;
const meta::class_type clazz_type = meta::resolve_type<clazz_t>();
REQUIRE(clazz_type);
SUBCASE("int") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<int>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, int>());
}
{
const meta::uvalue v = clazz_type.create(42);
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
CHECK(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<clazz_t&&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, clazz_t&&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::move(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
CHECK(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("const clazz_t&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<const clazz_t&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, const clazz_t&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::as_const(o));
CHECK(v.get_type() == meta::resolve_type<clazz_t*>());
CHECK(v.get_as<clazz_t*>()->i == 42);
CHECK(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 1);
}
}
TEST_CASE("meta/meta_states/ctor/as_shared_pointer") {
namespace meta = meta_hpp;
using clazz_t = clazz<meta::constructor_policy::as_shared_pointer_t>;
meta::class_<clazz_t>()
.constructor_<int>(meta::constructor_policy::as_shared_pointer)
.constructor_<clazz_t&&>(meta::constructor_policy::as_shared_pointer)
.constructor_<const clazz_t&>(meta::constructor_policy::as_shared_pointer);
clazz_t::constructor_counter = 0;
clazz_t::destructor_counter = 0;
clazz_t::move_constructor_counter = 0;
clazz_t::copy_constructor_counter = 0;
const meta::class_type clazz_type = meta::resolve_type<clazz_t>();
REQUIRE(clazz_type);
SUBCASE("int") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<int>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, int>());
}
{
const meta::uvalue v = clazz_type.create(42);
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz_t>>());
CHECK(v.get_as<std::shared_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 1);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("clazz_t&&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<clazz_t&&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, clazz_t&&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::move(o));
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz_t>>());
CHECK(v.get_as<std::shared_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 1);
CHECK(clazz_t::copy_constructor_counter == 0);
}
SUBCASE("const clazz_t&") {
{
const meta::constructor ctor = clazz_type.get_constructor_with<const clazz_t&>();
REQUIRE(ctor);
CHECK(ctor.get_type() == meta::resolve_constructor_type<clazz_t, const clazz_t&>());
}
{
clazz_t o{42};
const meta::uvalue v = clazz_type.create(std::as_const(o));
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz_t>>());
CHECK(v.get_as<std::shared_ptr<clazz_t>>()->i == 42);
CHECK_FALSE(clazz_type.destroy(v));
}
CHECK(clazz_t::constructor_counter == 1);
CHECK(clazz_t::destructor_counter == 2);
CHECK(clazz_t::move_constructor_counter == 0);
CHECK(clazz_t::copy_constructor_counter == 1);
}
}

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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
{
class clazz_closed_dtor {
public:
~clazz_closed_dtor() = delete;
};
class clazz_opened_dtor {
public:
~clazz_opened_dtor() = default;
};
class clazz_virtual_dtor {
public:
virtual ~clazz_virtual_dtor() noexcept(false) = default;
};
class clazz_dtor_metadata {
public:
virtual ~clazz_dtor_metadata() = default;
};
}
TEST_CASE("meta/meta_states/dtor") {
namespace meta = meta_hpp;
using namespace std::string_literals;
meta::class_<clazz_opened_dtor>();
meta::class_<clazz_closed_dtor>();
meta::class_<clazz_virtual_dtor>();
meta::class_<clazz_dtor_metadata>()
.destructor_({
.metadata{
{"desc", meta::uvalue{"virtual dtor"s}}
}
});
SUBCASE("closed_dtor") {
const meta::class_type clazz_type = meta::resolve_type<clazz_closed_dtor>();
REQUIRE(clazz_type);
CHECK(clazz_type.get_destructors().empty());
}
SUBCASE("opened_dtor") {
const meta::class_type clazz_type = meta::resolve_type<clazz_opened_dtor>();
REQUIRE(clazz_type);
REQUIRE(clazz_type.get_destructors().size() == 1);
const meta::destructor dtor = clazz_type.get_destructor();
CHECK(dtor.get_type().get_class_type() == meta::resolve_type<clazz_opened_dtor>());
CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_noexcept);
}
SUBCASE("virtual_dtor") {
const meta::class_type clazz_type = meta::resolve_type<clazz_virtual_dtor>();
REQUIRE(clazz_type);
REQUIRE(clazz_type.get_destructors().size() == 1);
const meta::destructor dtor = clazz_type.get_destructor();
CHECK(dtor.get_type().get_class_type() == meta::resolve_type<clazz_virtual_dtor>());
CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_virtual);
}
SUBCASE("virtual_dtor") {
const meta::class_type clazz_type = meta::resolve_type<clazz_virtual_dtor>();
REQUIRE(clazz_type);
REQUIRE(clazz_type.get_destructors().size() == 1);
const meta::destructor dtor = clazz_type.get_destructor();
CHECK(dtor.get_type().get_class_type() == meta::resolve_type<clazz_virtual_dtor>());
CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_virtual);
}
SUBCASE("dtor_metadata") {
const meta::class_type clazz_type = meta::resolve_type<clazz_dtor_metadata>();
REQUIRE(clazz_type);
REQUIRE(clazz_type.get_destructors().size() == 1);
const meta::destructor dtor = clazz_type.get_destructor();
CHECK(dtor.get_type().get_class_type() == meta::resolve_type<clazz_dtor_metadata>());
CHECK(dtor.get_type().get_flags() == (meta::destructor_flags::is_noexcept | meta::destructor_flags::is_virtual));
CHECK(dtor.get_metadata().at("desc") == "virtual dtor"s);
}
}

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* 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
{
enum class color : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
white = red | green | blue,
};
}
TEST_CASE("meta/meta_states/evalue") {
namespace meta = meta_hpp;
meta::enum_<color>()
.evalue_("red", color::red)
.evalue_("green", color::green)
.evalue_("blue", color::blue)
.evalue_("white", color::white);
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
SUBCASE("") {
const meta::evalue evalue;
CHECK_FALSE(evalue);
CHECK_FALSE(evalue.is_valid());
CHECK(evalue == color_type.get_evalue("non-existent-evalue"));
}
SUBCASE("operators") {
const meta::evalue blue_e = color_type.get_evalue("blue");
const meta::evalue white_e = color_type.get_evalue("white");
CHECK(blue_e == blue_e);
CHECK(blue_e != white_e);
CHECK((blue_e < white_e || white_e < blue_e));
}
SUBCASE("green") {
const meta::evalue evalue = color_type.get_evalue("green");
REQUIRE(evalue);
CHECK(evalue.get_index().get_type() == evalue.get_type());
CHECK(evalue.get_index().get_name() == "green");
CHECK(evalue.get_type() == meta::resolve_type<color>());
CHECK(evalue.get_name() == "green");
CHECK(evalue.get_value() == color::green);
CHECK(evalue.get_value().get_type() == color_type);
CHECK(evalue.get_underlying_value() == meta::detail::to_underlying(color::green));
CHECK(evalue.get_underlying_value().get_type() == color_type.get_underlying_type());
}
}

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
static ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
static ivec2 isub(const ivec2& l, const ivec2& r) noexcept {
return {l.x - r.x, l.y - r.y};
}
};
}
TEST_CASE("meta/meta_states/function2") {
namespace meta = meta_hpp;
meta::class_<ivec2>()
.function_("iadd", &ivec2::iadd, { "l" })
.function_("isub", &ivec2::isub, { "l", "r" });
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
REQUIRE(ivec2_type);
SUBCASE("iadd2") {
const meta::function func = ivec2_type.get_function("iadd");
REQUIRE(func);
CHECK(func.get_arguments().size() == 2);
REQUIRE(func.get_argument(0));
CHECK(func.get_argument(0).get_type() == meta::resolve_type<const ivec2&>());
CHECK(func.get_argument(0).get_position() == 0);
CHECK(func.get_argument(0).get_name() == "l");
REQUIRE(func.get_argument(1));
CHECK(func.get_argument(1).get_type() == meta::resolve_type<const ivec2&>());
CHECK(func.get_argument(1).get_position() == 1);
CHECK(func.get_argument(1).get_name() == "");
CHECK_FALSE(func.get_argument(2));
}
SUBCASE("isub2") {
const meta::function func = ivec2_type.get_function("isub");
REQUIRE(func);
REQUIRE(func.get_arguments().size() == 2);
REQUIRE(func.get_argument(0));
CHECK(func.get_argument(0).get_type() == meta::resolve_type<const ivec2&>());
CHECK(func.get_argument(0).get_position() == 0);
CHECK(func.get_argument(0).get_name() == "l");
REQUIRE(func.get_argument(1));
CHECK(func.get_argument(1).get_type() == meta::resolve_type<const ivec2&>());
CHECK(func.get_argument(1).get_position() == 1);
CHECK(func.get_argument(1).get_name() == "r");
CHECK_FALSE(func.get_argument(2));
}
}

View File

@@ -0,0 +1,247 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
static ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
static int ilength2(const ivec2& v) noexcept {
return v.x * v.x + v.y * v.y;
}
static bool arg_nullptr(const void* ptr) { return ptr == nullptr; }
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; }
};
[[maybe_unused]] bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
}
TEST_CASE("meta/meta_states/function") {
namespace meta = meta_hpp;
meta::class_<ivec2>()
.function_("iadd", &ivec2::iadd)
.function_("ilength2", &ivec2::ilength2)
.function_("arg_nullptr", &ivec2::arg_nullptr)
.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>();
REQUIRE(ivec2_type);
SUBCASE("") {
const meta::function func;
CHECK_FALSE(func);
CHECK_FALSE(func.is_valid());
CHECK(func == ivec2_type.get_function("non-existent-function"));
}
SUBCASE("operators") {
const meta::function iadd_f = ivec2_type.get_function("iadd");
const meta::function ilength2_f = ivec2_type.get_function("ilength2");
CHECK(iadd_f == iadd_f);
CHECK(iadd_f != ilength2_f);
CHECK((iadd_f < ilength2_f || ilength2_f < iadd_f));
}
SUBCASE("iadd") {
const meta::function func = ivec2_type.get_function("iadd");
REQUIRE(func);
CHECK(func.get_index().get_type() == func.get_type());
CHECK(func.get_index().get_name() == "iadd");
CHECK(func.get_type() == meta::resolve_type(&ivec2::iadd));
CHECK(func.get_name() == "iadd");
CHECK_FALSE(func.is_invocable_with<>());
CHECK_FALSE(func.is_invocable_with<int>());
CHECK_FALSE(func.is_invocable_with<ivec2, int>());
CHECK_FALSE(func.is_invocable_with<int, ivec2>());
CHECK_FALSE(func.is_invocable_with<ivec2, ivec2, int>());
CHECK(func.is_invocable_with<ivec2, ivec2>());
CHECK(func.is_invocable_with<const ivec2&, ivec2&&>());
CHECK_THROWS(func.invoke());
CHECK_THROWS(func.invoke(42));
CHECK_THROWS(func.invoke(ivec2{}, 42));
CHECK_THROWS(func.invoke(42, ivec2{}));
CHECK_THROWS(func.invoke(ivec2{}, ivec2{}, 42));
CHECK(func.invoke(ivec2{1,2}, ivec2{3,4}));
CHECK(func.invoke(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
SUBCASE("ilength2") {
const meta::function func = ivec2_type.get_function("ilength2");
REQUIRE(func);
CHECK(func.get_index().get_type() == func.get_type());
CHECK(func.get_index().get_name() == "ilength2");
CHECK(func.get_type() == meta::resolve_type(&ivec2::ilength2));
CHECK(func.get_name() == "ilength2");
CHECK_FALSE(func.is_invocable_with<>());
CHECK_FALSE(func.is_invocable_with<int>());
CHECK_FALSE(func.is_invocable_with<ivec2, int>());
CHECK(func.is_invocable_with<ivec2>());
CHECK(func.is_invocable_with<const ivec2&>());
CHECK_THROWS(func.invoke());
CHECK_THROWS(func.invoke(42));
CHECK_THROWS(func.invoke(ivec2{}, 42));
CHECK(func.invoke(ivec2{2,3}));
CHECK(func.invoke(ivec2{2,3}) == 13);
}
SUBCASE("arg_null") {
const meta::function func = ivec2_type.get_function("arg_nullptr");
REQUIRE(func);
CHECK(func.is_invocable_with<int*>());
CHECK(func.is_invocable_with<const int*>());
CHECK(func.is_invocable_with<std::nullptr_t>());
int i{42};
CHECK(func.invoke(&i) == false);
CHECK(func.invoke(nullptr) == true);
}
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::uvalue{bounded_arr}) == 10);
CHECK(func1.invoke(meta::uvalue{unbounded_arr}) == 10);
CHECK_THROWS(func1.invoke(meta::uvalue{bounded_const_arr}));
CHECK_THROWS(func1.invoke(meta::uvalue{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::uvalue{bounded_arr}) == 10);
CHECK(func2.invoke(meta::uvalue{unbounded_arr}) == 10);
CHECK_THROWS(func2.invoke(meta::uvalue{bounded_const_arr}));
CHECK_THROWS(func2.invoke(meta::uvalue{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::uvalue{bounded_arr}) == 10);
CHECK(func1.invoke(meta::uvalue{unbounded_arr}) == 10);
CHECK(func1.invoke(meta::uvalue{bounded_const_arr}) == 10);
CHECK(func1.invoke(meta::uvalue{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::uvalue{bounded_arr}) == 10);
CHECK(func2.invoke(meta::uvalue{unbounded_arr}) == 10);
CHECK(func2.invoke(meta::uvalue{bounded_const_arr}) == 10);
CHECK(func2.invoke(meta::uvalue{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)>);
}
}
}

View File

@@ -0,0 +1,313 @@
/*******************************************************************************
* 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 clazz_1 {
int int_member = 1;
const int const_int_member = 2;
std::unique_ptr<int> unique_int_member = std::make_unique<int>(42);
};
struct clazz_2 {};
}
TEST_CASE("meta/meta_states/member") {
namespace meta = meta_hpp;
meta::class_<clazz_1>()
.member_("int_member", &clazz_1::int_member)
.member_("const_int_member", &clazz_1::const_int_member)
// .member_("unique_int_member", &clazz_1::unique_int_member)
.member_("unique_int_member_as_ptr", &clazz_1::unique_int_member, meta::member_policy::as_pointer)
.member_("unique_int_member_as_ref", &clazz_1::unique_int_member, meta::member_policy::as_reference_wrapper);
const meta::class_type clazz_1_type = meta::resolve_type<clazz_1>();
REQUIRE(clazz_1_type);
SUBCASE("") {
const meta::member member;
CHECK_FALSE(member);
CHECK_FALSE(member.is_valid());
CHECK(member == clazz_1_type.get_member("non-existent-member"));
}
SUBCASE("operators") {
meta::member int_member_m = clazz_1_type.get_member("int_member");
meta::member const_int_member_m = clazz_1_type.get_member("const_int_member");
CHECK(int_member_m == int_member_m);
CHECK(int_member_m != const_int_member_m);
CHECK((int_member_m < const_int_member_m || const_int_member_m < int_member_m));
}
SUBCASE("int") {
meta::member vm = clazz_1_type.get_member("int_member");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::int_member));
CHECK(vm.get_name() == "int_member");
clazz_1 v;
clazz_2 v2;
{
CHECK(vm.is_gettable_with<clazz_1>());
CHECK(vm.is_gettable_with<clazz_1*>());
CHECK(vm.is_gettable_with<clazz_1&>());
CHECK(vm.is_gettable_with<clazz_1&&>());
CHECK(vm.is_gettable_with<const clazz_1>());
CHECK(vm.is_gettable_with<const clazz_1*>());
CHECK(vm.is_gettable_with<const clazz_1&>());
CHECK(vm.is_gettable_with<const clazz_1&&>());
CHECK(vm.is_gettable_with(v));
CHECK(vm.is_gettable_with(&v));
CHECK(vm.is_gettable_with(std::as_const(v)));
CHECK(vm.is_gettable_with(&std::as_const(v)));
CHECK(vm.is_gettable_with(std::move(v)));
CHECK(vm.is_gettable_with(std::move(std::as_const(v))));
CHECK_FALSE(vm.is_gettable_with<clazz_2>());
CHECK_FALSE(vm.is_gettable_with<clazz_2*>());
CHECK_FALSE(vm.is_gettable_with(v2));
CHECK_FALSE(vm.is_gettable_with(&v2));
}
{
CHECK(vm.get(v) == 1);
CHECK(vm.get(&v) == 1);
CHECK(vm.get(std::as_const(v)) == 1);
CHECK(vm.get(&std::as_const(v)) == 1);
CHECK(vm.get(std::move(v)) == 1);
CHECK(vm.get(std::move(std::as_const(v))) == 1);
CHECK(vm(v) == 1);
CHECK(vm(&v) == 1);
CHECK(vm(std::as_const(v)) == 1);
CHECK(vm(&std::as_const(v)) == 1);
CHECK(vm(std::move(v)) == 1);
CHECK(vm(std::move(std::as_const(v))) == 1);
CHECK_THROWS(std::ignore = vm.get(v2));
CHECK_THROWS(std::ignore = vm.get(&v2));
CHECK_THROWS(std::ignore = vm(v2));
CHECK_THROWS(std::ignore = vm(&v2));
}
{
CHECK(vm.is_settable_with<clazz_1, int>());
CHECK(vm.is_settable_with<clazz_1*, int>());
CHECK(vm.is_settable_with<clazz_1&, int>());
CHECK(vm.is_settable_with<clazz_1&&, int>());
CHECK(vm.is_settable_with<clazz_1, int&&>());
CHECK(vm.is_settable_with<clazz_1*, int&&>());
CHECK(vm.is_settable_with<clazz_1&, int&&>());
CHECK(vm.is_settable_with<clazz_1&&, int&&>());
CHECK(vm.is_settable_with(v, 10));
CHECK(vm.is_settable_with(&v, 10));
CHECK(vm.is_settable_with(std::move(v), 12));
CHECK_FALSE(vm.is_settable_with<clazz_1, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, float>());
CHECK_FALSE(vm.is_settable_with<const clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2&, int>());
CHECK_FALSE(vm.is_settable_with(v2, 10));
CHECK_FALSE(vm.is_settable_with(&v2, 10));
CHECK_FALSE(vm.is_settable_with(std::move(v2), 10));
CHECK_FALSE(vm.is_settable_with(v, 10.0));
CHECK_FALSE(vm.is_settable_with(&v, 10.0));
CHECK_FALSE(vm.is_settable_with(std::move(v), 12.0));
}
{
CHECK_NOTHROW(vm.set(v, 10)); CHECK(vm.get(v) == 10);
CHECK_NOTHROW(vm.set(&v, 100)); CHECK(vm.get(v) == 100);
CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 100);
CHECK_THROWS(vm.set(&std::as_const(v), 11)); CHECK(vm.get(v) == 100);
CHECK_NOTHROW(vm.set(std::move(v), 12)); CHECK(vm.get(v) == 12);
CHECK_THROWS(vm.set(std::move(std::as_const(v)), 13)); CHECK(vm.get(v) == 12);
CHECK_NOTHROW(vm(v, 13)); CHECK(vm(v) == 13);
CHECK_NOTHROW(vm(&v, 130)); CHECK(vm(v) == 130);
CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 130);
CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 130);
CHECK_NOTHROW(vm(std::move(v), 15)); CHECK(vm(v) == 15);
CHECK_THROWS(vm(std::move(std::as_const(v)), 16)); CHECK(vm(v) == 15);
CHECK_THROWS(vm.set(v2, 17));
CHECK_THROWS(vm.set(&v2, 17));
CHECK_THROWS(vm(v2, 17));
CHECK_THROWS(vm(&v2, 17));
CHECK(vm(v) == 15);
}
}
SUBCASE("const int") {
meta::member vm = clazz_1_type.get_member("const_int_member");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::const_int_member));
CHECK(vm.get_name() == "const_int_member");
clazz_1 v;
clazz_2 v2;
{
CHECK(vm.is_gettable_with<clazz_1>());
CHECK(vm.is_gettable_with<clazz_1*>());
CHECK(vm.is_gettable_with<clazz_1&>());
CHECK(vm.is_gettable_with<clazz_1&&>());
CHECK(vm.is_gettable_with<const clazz_1>());
CHECK(vm.is_gettable_with<const clazz_1*>());
CHECK(vm.is_gettable_with<const clazz_1&>());
CHECK(vm.is_gettable_with<const clazz_1&&>());
CHECK(vm.is_gettable_with(v));
CHECK(vm.is_gettable_with(&v));
CHECK(vm.is_gettable_with(std::as_const(v)));
CHECK(vm.is_gettable_with(&std::as_const(v)));
CHECK(vm.is_gettable_with(std::move(v)));
CHECK(vm.is_gettable_with(std::move(std::as_const(v))));
CHECK_FALSE(vm.is_gettable_with<clazz_2>());
CHECK_FALSE(vm.is_gettable_with<clazz_2*>());
CHECK_FALSE(vm.is_gettable_with(v2));
CHECK_FALSE(vm.is_gettable_with(&v2));
}
{
CHECK(vm.get(v) == 2);
CHECK(vm.get(&v) == 2);
CHECK(vm.get(std::as_const(v)) == 2);
CHECK(vm.get(&std::as_const(v)) == 2);
CHECK(vm.get(std::move(v)) == 2);
CHECK(vm.get(std::move(std::as_const(v))) == 2);
CHECK(vm(v) == 2);
CHECK(vm(&v) == 2);
CHECK(vm(std::as_const(v)) == 2);
CHECK(vm(&std::as_const(v)) == 2);
CHECK(vm(std::move(v)) == 2);
CHECK(vm(std::move(std::as_const(v))) == 2);
CHECK_THROWS(std::ignore = vm.get(v2));
CHECK_THROWS(std::ignore = vm.get(&v2));
CHECK_THROWS(std::ignore = vm(v2));
CHECK_THROWS(std::ignore = vm(&v2));
}
{
CHECK_FALSE(vm.is_settable_with<clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, float>());
CHECK_FALSE(vm.is_settable_with<const clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&&, int>());
CHECK_FALSE(vm.is_settable_with(v, 10));
CHECK_FALSE(vm.is_settable_with(&v, 10));
CHECK_FALSE(vm.is_settable_with(std::move(v), 12));
CHECK_FALSE(vm.is_settable_with<clazz_2*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2&, int>());
CHECK_FALSE(vm.is_settable_with(v2, 10));
CHECK_FALSE(vm.is_settable_with(&v2, 10));
CHECK_FALSE(vm.is_settable_with(std::move(v2), 12));
}
{
CHECK_THROWS(vm.set(v, 10)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm.set(&v, 10)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm.set(&std::as_const(v), 11)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm.set(std::move(v), 12)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm.set(std::move(std::as_const(v)), 16)); CHECK(vm.get(v) == 2);
CHECK_THROWS(vm(v, 13)); CHECK(vm(v) == 2);
CHECK_THROWS(vm(&v, 13)); CHECK(vm(v) == 2);
CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 2);
CHECK_THROWS(vm(&std::as_const(v), 14)); CHECK(vm(v) == 2);
CHECK_THROWS(vm(std::move(v), 15)); CHECK(vm(v) == 2);
CHECK_THROWS(vm(std::move(std::as_const(v)), 16)); CHECK(vm(v) == 2);
CHECK_THROWS(vm.set(v2, 17));
CHECK_THROWS(vm.set(&v2, 17));
CHECK_THROWS(vm(v2, 17));
CHECK_THROWS(vm(&v2, 17));
CHECK(vm(v) == 2);
}
}
SUBCASE("unique_int_member_as_ptr") {
meta::member vm = clazz_1_type.get_member("unique_int_member_as_ptr");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::unique_int_member));
CHECK(vm.get_name() == "unique_int_member_as_ptr");
{
clazz_1 v;
CHECK(vm.get(v).get_type() == meta::resolve_type<std::unique_ptr<int>*>());
CHECK(vm.get(v) == std::addressof(v.unique_int_member));
}
{
const clazz_1 v;
CHECK(vm.get(v).get_type() == meta::resolve_type<const std::unique_ptr<int>*>());
CHECK(vm.get(v) == std::addressof(v.unique_int_member));
}
}
SUBCASE("unique_int_member_as_ref") {
meta::member vm = clazz_1_type.get_member("unique_int_member_as_ref");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::unique_int_member));
CHECK(vm.get_name() == "unique_int_member_as_ref");
{
clazz_1 v;
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get(v).get_as<ref_t>().get() == v.unique_int_member);
}
{
const clazz_1 v;
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get(v).get_as<ref_t>().get() == v.unique_int_member);
}
}
}

View File

@@ -0,0 +1,325 @@
/*******************************************************************************
* 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
{
enum class color : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
};
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] explicit ivec2(int nv) : x{nv}, y{nv} {}
[[maybe_unused]] ivec2(int nx, int ny) : x{nx}, y{ny} {}
ivec2& add(const ivec2& other) noexcept {
x += other.x;
y += other.y;
return *this;
}
static ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
};
}
TEST_CASE("meta/meta_states/metadata/enum") {
namespace meta = meta_hpp;
using namespace std::string_literals;
meta::enum_<color>({
{"desc1", meta::uvalue{"enum-desc1"s}},
{"desc2", meta::uvalue{"enum-desc2"s}},
})
.evalue_("red", color::red, {
.metadata{{"desc1", meta::uvalue{"red-color"s}}}
})
.evalue_("green", color::green, {
.metadata{{"desc1", meta::uvalue{"green-color"s}}}
})
.evalue_("blue", color::blue, {
.metadata{{"desc1", meta::uvalue{"blue-color"s}}}
});
// metadata override
meta::enum_<color>({
{"desc2", meta::uvalue{"new-enum-desc2"s}},
{"desc3", meta::uvalue{"new-enum-desc3"s}},
});
meta::enum_<color>()
.evalue_("red", color::red, {
.metadata{
{"desc2", meta::uvalue{"new-red-color"s}},
}
});
//
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
SUBCASE("color") {
CHECK(color_type.get_metadata().at("desc1") == "enum-desc1"s);
CHECK(color_type.get_metadata().at("desc2") == "new-enum-desc2"s);
CHECK(color_type.get_metadata().at("desc3") == "new-enum-desc3"s);
}
SUBCASE("color::red") {
const meta::evalue red_evalue = color_type.get_evalue("red");
REQUIRE(red_evalue);
CHECK_FALSE(red_evalue.get_metadata().contains("desc1"));
CHECK(red_evalue.get_metadata().at("desc2") == "new-red-color"s);
}
}
TEST_CASE("meta/meta_states/metadata/class") {
namespace meta = meta_hpp;
using namespace std::string_literals;
meta::class_<ivec2>({
{"desc1", meta::uvalue{"class-desc1"s}},
{"desc2", meta::uvalue{"class-desc2"s}},
})
.constructor_<int>({
.arguments{{
.name{"v"},
.metadata{{"desc", meta::uvalue{"the ctor arg"s}}},
}},
.metadata{{"desc", meta::uvalue{"one arg 2d vector ctor"s}}},
})
.constructor_<int, int>({
.arguments{{
.name{"x"},
.metadata{{"desc", meta::uvalue{"the 1st ctor arg"s}}},
},{
.name{"y"},
.metadata{{"desc", meta::uvalue{"the 2nd ctor arg"s}}},
}},
.metadata{{"desc", meta::uvalue{"two args 2d vector ctor"s}}}
})
.member_("x", &ivec2::x, {
.metadata{{"desc", meta::uvalue{"x-member"s}}}
})
.member_("y", &ivec2::y, {
.metadata{{"desc", meta::uvalue{"y-member"s}}}
})
.method_("add", &ivec2::add, {
.arguments{{
.name{"other"},
.metadata{{"desc", meta::uvalue{"other-arg"s}}}
}},
.metadata{{"desc", meta::uvalue{"add-method"s}}}
})
.function_("iadd", &ivec2::iadd, {
.arguments{{
.name{"l"},
.metadata{{"desc", meta::uvalue{"l-arg"s}}}
},{
.name{"r"},
.metadata{{"desc", meta::uvalue{"r-arg"s}}}
}},
.metadata{{"desc", meta::uvalue{"iadd-function"s}}}
});
// metadata override
meta::class_<ivec2>({
{"desc2", meta::uvalue{"new-class-desc2"s}},
{"desc3", meta::uvalue{"new-class-desc3"s}},
});
//
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
REQUIRE(ivec2_type);
SUBCASE("ivec2") {
CHECK(ivec2_type.get_metadata().at("desc1") == "class-desc1"s);
CHECK(ivec2_type.get_metadata().at("desc2") == "new-class-desc2"s);
CHECK(ivec2_type.get_metadata().at("desc3") == "new-class-desc3"s);
}
SUBCASE("ivec2(int)") {
const meta::constructor ivec2_ctor = ivec2_type.get_constructor_with<int>();
REQUIRE(ivec2_ctor);
REQUIRE(ivec2_ctor.get_metadata().contains("desc"));
CHECK(ivec2_ctor.get_metadata().at("desc") == "one arg 2d vector ctor"s);
REQUIRE(ivec2_ctor.get_argument(0));
CHECK(ivec2_ctor.get_argument(0).get_name() == "v");
CHECK(ivec2_ctor.get_argument(0).get_position() == 0);
CHECK(ivec2_ctor.get_argument(0).get_type() == meta::resolve_type<int>());
REQUIRE(ivec2_ctor.get_argument(0).get_metadata().contains("desc"));
CHECK(ivec2_ctor.get_argument(0).get_metadata().at("desc") == "the ctor arg"s);
REQUIRE_FALSE(ivec2_ctor.get_argument(1));
}
SUBCASE("ivec2(int, int)") {
const meta::constructor ivec2_ctor = ivec2_type.get_constructor_with<int, int>();
REQUIRE(ivec2_ctor);
REQUIRE(ivec2_ctor.get_metadata().contains("desc"));
CHECK(ivec2_ctor.get_metadata().at("desc") == "two args 2d vector ctor"s);
REQUIRE(ivec2_ctor.get_argument(0));
CHECK(ivec2_ctor.get_argument(0).get_name() == "x");
CHECK(ivec2_ctor.get_argument(0).get_position() == 0);
CHECK(ivec2_ctor.get_argument(0).get_type() == meta::resolve_type<int>());
REQUIRE(ivec2_ctor.get_argument(0).get_metadata().contains("desc"));
CHECK(ivec2_ctor.get_argument(0).get_metadata().at("desc") == "the 1st ctor arg"s);
REQUIRE(ivec2_ctor.get_argument(1));
CHECK(ivec2_ctor.get_argument(1).get_name() == "y");
CHECK(ivec2_ctor.get_argument(1).get_position() == 1);
CHECK(ivec2_ctor.get_argument(1).get_type() == meta::resolve_type<int>());
REQUIRE(ivec2_ctor.get_argument(1).get_metadata().contains("desc"));
CHECK(ivec2_ctor.get_argument(1).get_metadata().at("desc") == "the 2nd ctor arg"s);
REQUIRE_FALSE(ivec2_ctor.get_argument(2));
}
SUBCASE("ivec2::x") {
const meta::member ivec2_x = ivec2_type.get_member("x");
REQUIRE(ivec2_x);
REQUIRE(ivec2_x.get_metadata().contains("desc"));
CHECK(ivec2_x.get_metadata().at("desc") == "x-member"s);
}
SUBCASE("ivec2::y") {
const meta::member ivec2_y = ivec2_type.get_member("y");
REQUIRE(ivec2_y);
REQUIRE(ivec2_y.get_metadata().contains("desc"));
CHECK(ivec2_y.get_metadata().at("desc") == "y-member"s);
}
SUBCASE("ivec2::add") {
const meta::method ivec2_add = ivec2_type.get_method("add");
REQUIRE(ivec2_add);
REQUIRE(ivec2_add.get_metadata().contains("desc"));
CHECK(ivec2_add.get_metadata().at("desc") == "add-method"s);
REQUIRE(ivec2_add.get_argument(0));
REQUIRE(ivec2_add.get_argument(0).get_metadata().contains("desc"));
CHECK(ivec2_add.get_argument(0).get_metadata().at("desc") == "other-arg"s);
}
SUBCASE("ivec2::iadd") {
const meta::function ivec2_iadd = ivec2_type.get_function("iadd");
REQUIRE(ivec2_iadd);
REQUIRE(ivec2_iadd.get_metadata().contains("desc"));
CHECK(ivec2_iadd.get_metadata().at("desc") == "iadd-function"s);
REQUIRE(ivec2_iadd.get_argument(0));
REQUIRE(ivec2_iadd.get_argument(0).get_metadata().contains("desc"));
CHECK(ivec2_iadd.get_argument(0).get_metadata().at("desc") == "l-arg"s);
REQUIRE(ivec2_iadd.get_argument(1));
REQUIRE(ivec2_iadd.get_argument(1).get_metadata().contains("desc"));
CHECK(ivec2_iadd.get_argument(1).get_metadata().at("desc") == "r-arg"s);
}
}
TEST_CASE("meta/meta_states/metadata/scope") {
namespace meta = meta_hpp;
using namespace std::string_literals;
SUBCASE("local_scope") {
const meta::scope lscope = meta::local_scope_("local-scope", {
{"desc", meta::uvalue{"scope-desc"s}}
});
CHECK(lscope.get_metadata().at("desc") == "scope-desc"s);
}
SUBCASE("static_scope") {
meta::static_scope_("meta/meta_states/metadata/scope/static-scope", {
{"desc", meta::uvalue{"scope-desc"s}}
});
CHECK(meta::resolve_scope("meta/meta_states/metadata/scope/static-scope").get_metadata().at("desc") == "scope-desc"s);
}
}
TEST_CASE("meta/meta_states/metadata/other") {
namespace meta = meta_hpp;
using namespace std::string_literals;
SUBCASE("array") {
meta::array_<int[]>({
{"desc", meta::uvalue{"int[]-type"s}}
});
CHECK(meta::resolve_type<int[]>().get_metadata().at("desc") == "int[]-type"s);
}
SUBCASE("function") {
meta::function_<int(*)(int)>({
{"desc", meta::uvalue{"int->int"s}}
});
CHECK(meta::resolve_type<int(*)(int)>().get_metadata().at("desc") == "int->int"s);
}
SUBCASE("member") {
meta::member_<int ivec2::*>({
{"desc", meta::uvalue{"ivec2::int"s}}
});
CHECK(meta::resolve_type<int ivec2::*>().get_metadata().at("desc") == "ivec2::int"s);
}
SUBCASE("method") {
meta::method_<int (ivec2::*)(int)>({
{"desc", meta::uvalue{"ivec2(int -> int)"s}}
});
CHECK(meta::resolve_type<int (ivec2::*)(int)>().get_metadata().at("desc") == "ivec2(int -> int)"s);
}
SUBCASE("nullptr") {
meta::nullptr_<std::nullptr_t>({
{"desc", meta::uvalue{"nullptr_t"s}}
});
CHECK(meta::resolve_type<std::nullptr_t>().get_metadata().at("desc") == "nullptr_t"s);
}
SUBCASE("number") {
meta::number_<int>({
{"desc", meta::uvalue{"int-type"s}}
});
CHECK(meta::resolve_type<int>().get_metadata().at("desc") == "int-type"s);
}
SUBCASE("pointer") {
meta::pointer_<int*>({
{"desc", meta::uvalue{"int*-type"s}}
});
CHECK(meta::resolve_type<int*>().get_metadata().at("desc") == "int*-type"s);
}
SUBCASE("reference") {
meta::reference_<int&>({
{"desc", meta::uvalue{"int&-type"s}}
});
CHECK(meta::resolve_type<int&>().get_metadata().at("desc") == "int&-type"s);
}
SUBCASE("void") {
meta::void_<void>({
{"desc", meta::uvalue{"void-type"s}}
});
CHECK(meta::resolve_type<void>().get_metadata().at("desc") == "void-type"s);
}
}

View File

@@ -0,0 +1,45 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
ivec2& add(const ivec2& other) {
x += other.x;
y += other.y;
return *this;
}
};
}
TEST_CASE("meta/meta_states/method2") {
namespace meta = meta_hpp;
meta::class_<ivec2>()
.method_("add", &ivec2::add, {"other"});
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
REQUIRE(ivec2_type);
SUBCASE("add") {
const meta::method add_m = ivec2_type.get_method("add");
REQUIRE(add_m);
CHECK(add_m.get_arguments().size() == 1);
REQUIRE(add_m.get_argument(0));
CHECK(add_m.get_argument(0).get_type() == meta::resolve_type<const ivec2&>());
CHECK(add_m.get_argument(0).get_position() == 0);
CHECK(add_m.get_argument(0).get_name() == "other");
CHECK_FALSE(add_m.get_argument(1));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,206 @@
/*******************************************************************************
* 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
{
enum class color {
red,
green,
blue,
};
struct ivec2 {
int x{};
int y{};
};
struct ivec3 {
int x{};
int y{};
int z{};
};
ivec2 iadd2(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
ivec3 iadd3(const ivec3& l, const ivec3& r) noexcept {
return {l.x + r.x, l.y + r.y, l.z + r.z};
}
int function_overloaded(int i0) { return i0; }
int function_overloaded(int i0, int i1) { return i0 + i1; }
ivec2 static_ivec2 = ivec2{1, 0};
const ivec3 static_const_ivec3 = ivec3{1, 0};
}
TEST_CASE("meta/meta_states/scope") {
namespace meta = meta_hpp;
meta::static_scope_("meta/meta_states/scope/math")
.typedef_<color>("color")
.typedef_<ivec2>("ivec2")
.typedef_<ivec3>("ivec3")
.function_("iadd2", &iadd2, {"l", "r"})
.function_("iadd3", &iadd3, {"l"})
.function_("function_overloaded", meta::select_overload<int(int)>(&function_overloaded))
.function_("function_overloaded", meta::select_overload<int(int,int)>(&function_overloaded))
.variable_("static_ivec2", &static_ivec2)
.variable_("static_const_ivec3", &static_const_ivec3);
const meta::scope math_scope = meta::resolve_scope("meta/meta_states/scope/math");
REQUIRE(math_scope);
REQUIRE(math_scope.is_valid());
CHECK(math_scope.get_name() == "meta/meta_states/scope/math");
CHECK(math_scope.get_variables().size() == 2);
CHECK(math_scope.get_typedefs().size() == 3);
SUBCASE("") {
const meta::scope scope;
CHECK_FALSE(scope);
CHECK_FALSE(scope.is_valid());
}
SUBCASE("operators") {
const meta::scope math1_s = meta::resolve_scope("meta/meta_states/scope/math1");
const meta::scope math2_s = meta::resolve_scope("meta/meta_states/scope/math2");
CHECK(math1_s == math1_s);
CHECK(math1_s != math2_s);
CHECK((math1_s < math2_s || math2_s < math1_s));
}
SUBCASE("classes") {
CHECK_FALSE(math_scope.get_typedef("non-existent-class"));
const meta::any_type ivec2_type = math_scope.get_typedef("ivec2");
CHECK(ivec2_type == meta::resolve_type<ivec2>());
const meta::any_type ivec3_type = math_scope.get_typedef("ivec3");
CHECK(ivec3_type == meta::resolve_type<ivec3>());
}
SUBCASE("enums") {
CHECK_FALSE(math_scope.get_typedef("non-existent-enum"));
const meta::any_type color_type = math_scope.get_typedef("color");
CHECK(color_type == meta::resolve_type<color>());
}
SUBCASE("functions") {
CHECK_FALSE(math_scope.get_function("non-existent-function"));
const meta::function iadd2_func = math_scope.get_function("iadd2");
REQUIRE(iadd2_func);
{
CHECK(iadd2_func.get_arguments().size() == 2);
REQUIRE(iadd2_func.get_argument(0));
CHECK(iadd2_func.get_argument(0).get_type() == meta::resolve_type<const ivec2&>());
CHECK(iadd2_func.get_argument(0).get_position() == 0);
CHECK(iadd2_func.get_argument(0).get_name() == "l");
REQUIRE(iadd2_func.get_argument(1));
CHECK(iadd2_func.get_argument(1).get_type() == meta::resolve_type<const ivec2&>());
CHECK(iadd2_func.get_argument(1).get_position() == 1);
CHECK(iadd2_func.get_argument(1).get_name() == "r");
CHECK_FALSE(iadd2_func.get_argument(2));
}
const meta::function iadd3_func = math_scope.get_function("iadd3");
REQUIRE(iadd3_func);
{
CHECK(iadd3_func.get_arguments().size() == 2);
REQUIRE(iadd3_func.get_argument(0));
CHECK(iadd3_func.get_argument(0).get_type() == meta::resolve_type<const ivec3&>());
CHECK(iadd3_func.get_argument(0).get_position() == 0);
CHECK(iadd3_func.get_argument(0).get_name() == "l");
REQUIRE(iadd3_func.get_argument(1));
CHECK(iadd3_func.get_argument(1).get_type() == meta::resolve_type<const ivec3&>());
CHECK(iadd3_func.get_argument(1).get_position() == 1);
CHECK(iadd3_func.get_argument(1).get_name() == "");
CHECK_FALSE(iadd3_func.get_argument(2));
}
}
SUBCASE("function_with") {
CHECK(math_scope.get_function("function_overloaded"));
{
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK(math_scope.get_function_with<int>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<int, float>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<float>("function_overloaded"));
CHECK(math_scope.get_function_with<int, int>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<float, float>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<double>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with<double, double>("function_overloaded"));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK(math_scope.get_function_with("function_overloaded", {int_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", {int_type, float_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", {float_type}));
CHECK(math_scope.get_function_with("function_overloaded", {int_type, int_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", {float_type, float_type}));
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", {double_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", {double_type, double_type}));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK(math_scope.get_function_with("function_overloaded", meta::any_type_list{int_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", meta::any_type_list{int_type, float_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", meta::any_type_list{float_type}));
CHECK(math_scope.get_function_with("function_overloaded", meta::any_type_list{int_type, int_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", meta::any_type_list{float_type, float_type}));
CHECK_FALSE(math_scope.get_function_with<>("function_overloaded"));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", meta::any_type_list{double_type}));
CHECK_FALSE(math_scope.get_function_with("function_overloaded", meta::any_type_list{double_type, double_type}));
}
}
SUBCASE("variables") {
CHECK_FALSE(math_scope.get_variable("non-existent-variable"));
const meta::variable static_ivec2_var = math_scope.get_variable("static_ivec2");
REQUIRE(static_ivec2_var);
CHECK(static_ivec2_var.get_type().get_data_type() == meta::resolve_type<ivec2>());
const meta::variable static_const_ivec3_var = math_scope.get_variable("static_const_ivec3");
REQUIRE(static_const_ivec3_var);
CHECK(static_const_ivec3_var.get_type().get_data_type() == meta::resolve_type<ivec3>());
}
}

View File

@@ -0,0 +1,234 @@
/*******************************************************************************
* 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 clazz_1 {
static int int_variable;
static const int const_int_variable;
static int& ref_int_variable;
static const int& const_ref_int_variable;
static std::unique_ptr<int> unique_int_variable;
static const std::unique_ptr<int> const_unique_int_variable;
};
int clazz_1::int_variable = 1;
const int clazz_1::const_int_variable = 2;
int& clazz_1::ref_int_variable = clazz_1::int_variable;
const int& clazz_1::const_ref_int_variable = clazz_1::const_int_variable;
std::unique_ptr<int> clazz_1::unique_int_variable = std::make_unique<int>(42);
const std::unique_ptr<int> clazz_1::const_unique_int_variable = std::make_unique<int>(42);
}
TEST_CASE("meta/meta_states/variable") {
namespace meta = meta_hpp;
meta::class_<clazz_1>()
.variable_("int_variable", &clazz_1::int_variable)
.variable_("const_int_variable", &clazz_1::const_int_variable)
.variable_("ref_int_variable", &clazz_1::ref_int_variable)
.variable_("const_ref_int_variable", &clazz_1::const_ref_int_variable)
// .variable_("unique_int_variable", &clazz_1::unique_int_variable)
.variable_("unique_int_variable_as_ptr", &clazz_1::unique_int_variable, meta::variable_policy::as_pointer)
.variable_("unique_int_variable_as_ref", &clazz_1::unique_int_variable, meta::variable_policy::as_reference_wrapper)
// .variable_("const_unique_int_variable", &clazz_1::const_unique_int_variable)
.variable_("const_unique_int_variable_as_ptr", &clazz_1::const_unique_int_variable, meta::variable_policy::as_pointer)
.variable_("const_unique_int_variable_as_ref", &clazz_1::const_unique_int_variable, meta::variable_policy::as_reference_wrapper);
const meta::class_type clazz_1_type = meta::resolve_type<clazz_1>();
REQUIRE(clazz_1_type);
SUBCASE("") {
const meta::variable variable;
CHECK_FALSE(variable);
CHECK_FALSE(variable.is_valid());
CHECK(variable == clazz_1_type.get_variable("non-existent-variable"));
}
SUBCASE("operators") {
meta::variable int_variable_v = clazz_1_type.get_variable("int_variable");
meta::variable const_int_variable_v = clazz_1_type.get_variable("const_int_variable");
CHECK(int_variable_v == int_variable_v);
CHECK(int_variable_v != const_int_variable_v);
CHECK((int_variable_v < const_int_variable_v || const_int_variable_v < int_variable_v));
}
SUBCASE("int") {
meta::variable vm = clazz_1_type.get_variable("int_variable");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::int_variable));
CHECK(vm.get_name() == "int_variable");
CHECK(vm.get() == 1);
CHECK(vm() == 1);
CHECK(vm.is_settable_with<int>());
CHECK(vm.is_settable_with<int&&>());
CHECK(vm.is_settable_with<const int&>());
CHECK(vm.is_settable_with(1));
CHECK_FALSE(vm.is_settable_with<float>());
CHECK_FALSE(vm.is_settable_with<float&&>());
CHECK_FALSE(vm.is_settable_with<const float&>());
CHECK_FALSE(vm.is_settable_with(1.0));
CHECK_NOTHROW(vm.set(10)); CHECK(vm.get() == 10);
CHECK_NOTHROW(vm(11)); CHECK(vm() == 11);
}
SUBCASE("const int") {
meta::variable vm = clazz_1_type.get_variable("const_int_variable");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::const_int_variable));
CHECK(vm.get_name() == "const_int_variable");
CHECK(vm.get() == 2);
CHECK(vm() == 2);
CHECK_FALSE(vm.is_settable_with<int>());
CHECK_FALSE(vm.is_settable_with<int&&>());
CHECK_FALSE(vm.is_settable_with<const int&>());
CHECK_FALSE(vm.is_settable_with(1));
CHECK_FALSE(vm.is_settable_with<float>());
CHECK_FALSE(vm.is_settable_with<float&&>());
CHECK_FALSE(vm.is_settable_with<const float&>());
CHECK_FALSE(vm.is_settable_with(1.0));
CHECK_THROWS(vm.set(10)); CHECK(vm.get() == 2);
CHECK_THROWS(vm(10)); CHECK(vm() == 2);
}
SUBCASE("ref int") {
meta::variable vm = clazz_1_type.get_variable("ref_int_variable");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::ref_int_variable));
CHECK(vm.get_name() == "ref_int_variable");
CHECK(vm.get() == 11);
CHECK(vm() == 11);
CHECK(vm.is_settable_with<int>());
CHECK(vm.is_settable_with<int&&>());
CHECK(vm.is_settable_with<const int&>());
CHECK(vm.is_settable_with(1));
CHECK_FALSE(vm.is_settable_with<float>());
CHECK_FALSE(vm.is_settable_with<float&&>());
CHECK_FALSE(vm.is_settable_with<const float&>());
CHECK_FALSE(vm.is_settable_with(1.0));
CHECK_NOTHROW(vm.set(20)); CHECK(vm.get() == 20);
CHECK_NOTHROW(vm(21)); CHECK(vm() == 21);
}
SUBCASE("const ref int") {
meta::variable vm = clazz_1_type.get_variable("const_ref_int_variable");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::const_ref_int_variable));
CHECK(vm.get_name() == "const_ref_int_variable");
CHECK(vm.get() == 2);
CHECK(vm() == 2);
CHECK_FALSE(vm.is_settable_with<int>());
CHECK_FALSE(vm.is_settable_with<int&&>());
CHECK_FALSE(vm.is_settable_with<const int&>());
CHECK_FALSE(vm.is_settable_with(1));
CHECK_FALSE(vm.is_settable_with<float>());
CHECK_FALSE(vm.is_settable_with<float&&>());
CHECK_FALSE(vm.is_settable_with<const float&>());
CHECK_FALSE(vm.is_settable_with(1.0));
CHECK_THROWS(vm.set(10)); CHECK(vm.get() == 2);
CHECK_THROWS(vm(11)); CHECK(vm() == 2);
}
SUBCASE("unique_int_variable_as_ptr") {
meta::variable vm = clazz_1_type.get_variable("unique_int_variable_as_ptr");
REQUIRE(vm);
CHECK(vm.get().get_type() == meta::resolve_type<std::unique_ptr<int>*>());
CHECK(vm.get() == std::addressof(clazz_1::unique_int_variable));
{
auto nv = std::make_unique<int>(11);
CHECK_NOTHROW(vm.set(std::move(nv)));
CHECK(*clazz_1::unique_int_variable == 11);
}
{
auto nv = std::make_unique<int>(12);
CHECK_THROWS(vm.set(nv));
CHECK(*clazz_1::unique_int_variable == 11);
}
}
SUBCASE("unique_int_variable_as_ref") {
meta::variable vm = clazz_1_type.get_variable("unique_int_variable_as_ref");
REQUIRE(vm);
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get().get_as<ref_t>().get() == clazz_1::unique_int_variable);
{
auto nv = std::make_unique<int>(13);
CHECK_NOTHROW(vm.set(std::move(nv)));
CHECK(*clazz_1::unique_int_variable == 13);
}
{
auto nv = std::make_unique<int>(14);
CHECK_THROWS(vm.set(nv));
CHECK(*clazz_1::unique_int_variable == 13);
}
}
SUBCASE("const_unique_int_variable_as_ptr") {
meta::variable vm = clazz_1_type.get_variable("const_unique_int_variable_as_ptr");
REQUIRE(vm);
CHECK(vm.get().get_type() == meta::resolve_type<const std::unique_ptr<int>*>());
CHECK(vm.get() == std::addressof(clazz_1::const_unique_int_variable));
{
auto nv = std::make_unique<int>(11);
CHECK_THROWS(vm.set(nv));
CHECK_THROWS(vm.set(std::move(nv)));
CHECK(*clazz_1::const_unique_int_variable == 42);
}
}
SUBCASE("const_unique_int_variable_as_ref") {
meta::variable vm = clazz_1_type.get_variable("const_unique_int_variable_as_ref");
REQUIRE(vm);
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get().get_as<ref_t>().get() == clazz_1::const_unique_int_variable);
{
auto nv = std::make_unique<int>(12);
CHECK_THROWS(vm.set(nv));
CHECK_THROWS(vm.set(std::move(nv)));
CHECK(*clazz_1::const_unique_int_variable == 42);
}
}
}

View File

@@ -0,0 +1,258 @@
/*******************************************************************************
* 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 class_t {
class_t() = default;
[[maybe_unused]] class_t(int i): member_v{i} {}
int member_v{};
void method_v() {}
};
enum class enum_t {
evalue_v,
};
int array_v[42];
const class_t class_v;
const enum_t enum_v{enum_t::evalue_v};
void function_v() {}
const int number_v{42};
const int* pointer_v{&number_v};
}
TEST_CASE("meta/meta_types/any_type") {
namespace meta = meta_hpp;
meta::class_<class_t>()
.constructor_<>()
.constructor_<int>();
SUBCASE("") {
const meta::any_type type{};
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
CHECK_FALSE(type.is_array());
CHECK_FALSE(type.as_array());
}
SUBCASE("array") {
const meta::any_type& type = meta::resolve_type(array_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(array_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(array_v)>().get_id());
CHECK(type.is_array());
CHECK(type.get_kind() == meta::type_kind::array_);
CHECK_FALSE(type.is_class());
CHECK_FALSE(type.as_class());
const meta::array_type& specific_type = type.as_array();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("class") {
const meta::any_type& type = meta::resolve_type(class_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(class_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(class_v)>().get_id());
CHECK(type.is_class());
CHECK(type.get_kind() == meta::type_kind::class_);
CHECK_FALSE(type.is_constructor());
CHECK_FALSE(type.as_constructor());
const meta::class_type& specific_type = type.as_class();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("ctor") {
const meta::any_type& type = meta::resolve_type<class_t>()
.get_constructor_with<>()
.get_type();
REQUIRE(type);
CHECK(type.is_constructor());
CHECK(type.get_kind() == meta::type_kind::constructor_);
CHECK_FALSE(type.is_enum());
CHECK_FALSE(type.as_enum());
const meta::constructor_type& specific_type = type.as_constructor();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("enum") {
const meta::any_type& type = meta::resolve_type(enum_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(enum_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(enum_v)>().get_id());
CHECK(type.is_enum());
CHECK(type.get_kind() == meta::type_kind::enum_);
CHECK_FALSE(type.is_function());
CHECK_FALSE(type.as_function());
const meta::enum_type& specific_type = type.as_enum();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("function") {
const meta::any_type& type = meta::resolve_type(&function_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(&function_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(&function_v)>().get_id());
CHECK(type.is_function());
CHECK(type.get_kind() == meta::type_kind::function_);
CHECK_FALSE(type.is_member());
CHECK_FALSE(type.as_member());
const meta::function_type& specific_type = type.as_function();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("member") {
const meta::any_type& type = meta::resolve_type(&class_t::member_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(&class_t::member_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(&class_t::member_v)>().get_id());
CHECK(type.is_member());
CHECK(type.get_kind() == meta::type_kind::member_);
CHECK_FALSE(type.is_method());
CHECK_FALSE(type.as_method());
const meta::member_type& specific_type = type.as_member();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("method") {
const meta::any_type& type = meta::resolve_type(&class_t::method_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(&class_t::method_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(&class_t::method_v)>().get_id());
CHECK(type.is_method());
CHECK(type.get_kind() == meta::type_kind::method_);
CHECK_FALSE(type.is_nullptr());
CHECK_FALSE(type.as_nullptr());
const meta::method_type& specific_type = type.as_method();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("nullptr") {
const meta::any_type& type = meta::resolve_type(nullptr);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<std::nullptr_t>());
REQUIRE(type.get_id() == meta::resolve_type<std::nullptr_t>().get_id());
CHECK(type.is_nullptr());
CHECK(type.get_kind() == meta::type_kind::nullptr_);
CHECK_FALSE(type.is_number());
CHECK_FALSE(type.as_number());
const meta::nullptr_type& specific_type = type.as_nullptr();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("number") {
const meta::any_type& type = meta::resolve_type(number_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(number_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(number_v)>().get_id());
CHECK(type.is_number());
CHECK(type.get_kind() == meta::type_kind::number_);
CHECK_FALSE(type.is_pointer());
CHECK_FALSE(type.as_pointer());
const meta::number_type& specific_type = type.as_number();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("pointer") {
const meta::any_type& type = meta::resolve_type(pointer_v);
REQUIRE(type);
REQUIRE(type == meta::resolve_type<decltype(pointer_v)>());
REQUIRE(type.get_id() == meta::resolve_type<decltype(pointer_v)>().get_id());
CHECK(type.is_pointer());
CHECK(type.get_kind() == meta::type_kind::pointer_);
CHECK_FALSE(type.is_reference());
CHECK_FALSE(type.as_reference());
const meta::pointer_type& specific_type = type.as_pointer();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("reference") {
const meta::any_type& type = meta::resolve_type<const int&>();
REQUIRE(type);
CHECK(type.is_reference());
CHECK(type.get_kind() == meta::type_kind::reference_);
CHECK_FALSE(type.is_void());
CHECK_FALSE(type.as_void());
const meta::reference_type& specific_type = type.as_reference();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
SUBCASE("void") {
const meta::any_type& type = meta::resolve_type<void>();
REQUIRE(type);
CHECK(type.is_void());
CHECK(type.get_kind() == meta::type_kind::void_);
CHECK_FALSE(type.is_array());
CHECK_FALSE(type.as_array());
const meta::void_type& specific_type = type.as_void();
REQUIRE(specific_type);
CHECK(specific_type.get_id() == type.get_id());
}
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_types/array_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::array_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("int[]") {
const meta::array_type type = meta::resolve_type<int[]>();
REQUIRE(type);
CHECK(type.get_flags() == (meta::array_flags::is_unbounded));
CHECK(type.get_extent() == 0);
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("const unsigned[42][21]") {
const meta::array_type type = meta::resolve_type<const unsigned[42][21]>();
REQUIRE(type);
CHECK(type.get_flags() == (meta::array_flags::is_bounded));
CHECK(type.get_extent() == 42);
CHECK(type.get_data_type() == meta::resolve_type<const unsigned[21]>());
}
}

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* 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 clazz {
struct internal_clazz {};
enum class internal_enum {};
};
}
TEST_CASE("meta/meta_types/class_type2") {
namespace meta = meta_hpp;
meta::class_<clazz>()
.typedef_<clazz::internal_clazz>("internal_clazz")
.typedef_<clazz::internal_enum>("internal_enum");
const meta::class_type clazz_type = meta::resolve_type<clazz>();
REQUIRE(clazz_type);
CHECK(clazz_type.get_typedef("internal_clazz") == meta::resolve_type<clazz::internal_clazz>());
CHECK(clazz_type.get_typedef("internal_enum") == meta::resolve_type<clazz::internal_enum>());
CHECK(clazz_type.get_typedefs() == meta::typedef_map{
{"internal_clazz", meta::resolve_type<clazz::internal_clazz>()},
{"internal_enum", meta::resolve_type<clazz::internal_enum>()},
});
}

View File

@@ -0,0 +1,508 @@
/*******************************************************************************
* 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 base_clazz_1 {
base_clazz_1(int) {}
int base_member_1 = 1;
int base_method_1() { return 1; }
static int base_function_1() { return 1; }
int base_method_1_overloaded(int i0) const { return i0; }
int base_method_1_overloaded(float f0) const { return static_cast<int>(f0); }
static int base_function_1_overloaded(int i0) { return i0; }
static int base_function_1_overloaded(int i0, int i1) { return i0 + i1; }
static int base_variable_1;
};
int base_clazz_1::base_variable_1 = 1;
struct base_clazz_2 {
base_clazz_2(float) {}
float base_member_2 = 2.0f;
float base_method_2() { return 2.0f; }
static float base_function_2() { return 2.f; }
static float base_variable_2;
};
float base_clazz_2::base_variable_2 = 2.0f;
struct derived_clazz : base_clazz_1, base_clazz_2 {
[[maybe_unused]] derived_clazz(int i, float f)
: base_clazz_1{i}
, base_clazz_2{f} {}
double derived_member = 3.0;
double derived_method() { return 3.0; }
static double derived_function() { return 3.0; }
static constexpr double derived_variable = 3.0;
};
struct final_derived_clazz final : derived_clazz {
using derived_clazz::derived_clazz;
};
template < typename... Args >
struct variadic_clazz {};
}
TEST_CASE("meta/meta_types/class_type") {
namespace meta = meta_hpp;
meta::class_<base_clazz_1>()
.constructor_<int>()
.member_("base_member_1", &base_clazz_1::base_member_1)
.method_("base_method_1", &base_clazz_1::base_method_1)
.function_("base_function_1", &base_clazz_1::base_function_1)
.method_("base_method_1_overloaded", meta::select_overload<int(int) const>(&base_clazz_1::base_method_1_overloaded))
.method_("base_method_1_overloaded", meta::select_overload<int(float) const>(&base_clazz_1::base_method_1_overloaded))
.function_("base_function_1_overloaded", meta::select_overload<int(int)>(&base_clazz_1::base_function_1_overloaded))
.function_("base_function_1_overloaded", meta::select_overload<int(int,int)>(&base_clazz_1::base_function_1_overloaded))
.variable_("base_variable_1", &base_clazz_1::base_variable_1);
meta::class_<base_clazz_2>()
.constructor_<float>()
.member_("base_member_2", &base_clazz_2::base_member_2)
.method_("base_method_2", &base_clazz_2::base_method_2)
.function_("base_function_2", &base_clazz_2::base_function_2)
.variable_("base_variable_2", &base_clazz_2::base_variable_2);
meta::class_<derived_clazz>()
.constructor_<int, float>()
.base_<base_clazz_1>()
.base_<base_clazz_2>()
.member_("derived_member", &derived_clazz::derived_member)
.method_("derived_method", &derived_clazz::derived_method)
.function_("derived_function", &derived_clazz::derived_function)
.variable_("derived_variable", &derived_clazz::derived_variable);
meta::class_<final_derived_clazz>()
.constructor_<int, float>()
.base_<derived_clazz>();
const meta::class_type base_clazz_1_type = meta::resolve_type<base_clazz_1>();
REQUIRE(base_clazz_1_type);
const meta::class_type base_clazz_2_type = meta::resolve_type<base_clazz_2>();
REQUIRE(base_clazz_2_type);
const meta::class_type derived_clazz_type = meta::resolve_type<const derived_clazz>();
REQUIRE(derived_clazz_type);
const meta::class_type final_derived_clazz_type = meta::resolve_type<const final_derived_clazz>();
REQUIRE(final_derived_clazz_type);
const meta::class_type variadic_clazz_int_type = meta::resolve_type<variadic_clazz<int>>();
REQUIRE(variadic_clazz_int_type);
const meta::class_type variadic_clazz_int_float_type = meta::resolve_type<variadic_clazz<int, float>>();
REQUIRE(variadic_clazz_int_float_type);
SUBCASE("get_flags") {
CHECK(base_clazz_1_type.get_flags() == meta::class_flags{});
CHECK(base_clazz_2_type.get_flags() == meta::class_flags{});
CHECK(derived_clazz_type.get_flags() == meta::class_flags{});
CHECK(final_derived_clazz_type.get_flags() == meta::class_flags::is_final);
CHECK(variadic_clazz_int_type.get_flags() == (meta::class_flags::is_empty | meta::class_flags::is_template_instantiation));
CHECK(variadic_clazz_int_float_type.get_flags() == (meta::class_flags::is_empty | meta::class_flags::is_template_instantiation));
}
SUBCASE("get_size") {
CHECK(base_clazz_1_type.get_size() == sizeof(base_clazz_1));
CHECK(base_clazz_2_type.get_size() == sizeof(base_clazz_2));
CHECK(derived_clazz_type.get_size() == sizeof(derived_clazz));
CHECK(final_derived_clazz_type.get_size() == sizeof(final_derived_clazz));
}
SUBCASE("get_align") {
CHECK(base_clazz_1_type.get_align() == alignof(base_clazz_1));
CHECK(base_clazz_2_type.get_align() == alignof(base_clazz_2));
CHECK(derived_clazz_type.get_align() == alignof(derived_clazz));
CHECK(final_derived_clazz_type.get_align() == alignof(final_derived_clazz));
}
SUBCASE("get_arity") {
{
const meta::class_type type = meta::resolve_type<derived_clazz>();
REQUIRE(type);
CHECK(type.get_arity() == 0);
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int>>();
REQUIRE(type);
CHECK(type.get_arity() == 1);
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int, float>>();
REQUIRE(type);
CHECK(type.get_arity() == 2);
}
}
SUBCASE("get_argument_type") {
{
const meta::class_type type = meta::resolve_type<derived_clazz>();
REQUIRE(type);
CHECK_FALSE(type.get_argument_type(0));
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int>>();
REQUIRE(type);
CHECK(type.get_argument_type(0) == meta::resolve_type<int>());
CHECK_FALSE(type.get_argument_type(1));
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int, float>>();
REQUIRE(type);
CHECK(type.get_argument_type(0) == meta::resolve_type<int>());
CHECK(type.get_argument_type(1) == meta::resolve_type<float>());
CHECK_FALSE(type.get_argument_type(2));
}
}
SUBCASE("get_argument_types") {
{
const meta::class_type type = meta::resolve_type<derived_clazz>();
REQUIRE(type);
CHECK(type.get_argument_types() == meta::any_type_list{});
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int>>();
REQUIRE(type);
CHECK(type.get_argument_types() == meta::any_type_list{meta::resolve_type<int>()});
}
{
const meta::class_type type = meta::resolve_type<variadic_clazz<int, float>>();
REQUIRE(type);
CHECK(type.get_argument_types() == meta::any_type_list{meta::resolve_type<int>(), meta::resolve_type<float>()});
}
}
SUBCASE("get_constructors") {
CHECK(base_clazz_1_type.get_constructors().size() == 1);
CHECK(base_clazz_2_type.get_constructors().size() == 1);
CHECK(derived_clazz_type.get_constructors().size() == 1);
CHECK(final_derived_clazz_type.get_constructors().size() == 1);
}
SUBCASE("get_bases") {
CHECK(base_clazz_1_type.get_bases() == meta::class_set{});
CHECK(base_clazz_2_type.get_bases() == meta::class_set{});
CHECK(derived_clazz_type.get_bases() == meta::class_set{base_clazz_1_type, base_clazz_2_type});
CHECK(final_derived_clazz_type.get_bases() == meta::class_set{derived_clazz_type});
}
SUBCASE("get_functions") {
CHECK(base_clazz_1_type.get_functions().size() == 3);
CHECK(base_clazz_2_type.get_functions().size() == 1);
CHECK(derived_clazz_type.get_functions().size() == 1);
CHECK(final_derived_clazz_type.get_functions().size() == 0);
}
SUBCASE("get_members") {
CHECK(base_clazz_1_type.get_members().size() == 1);
CHECK(base_clazz_2_type.get_members().size() == 1);
CHECK(derived_clazz_type.get_members().size() == 1);
CHECK(final_derived_clazz_type.get_members().size() == 0);
}
SUBCASE("get_methods") {
CHECK(base_clazz_1_type.get_methods().size() == 3);
CHECK(base_clazz_2_type.get_methods().size() == 1);
CHECK(derived_clazz_type.get_methods().size() == 1);
CHECK(final_derived_clazz_type.get_methods().size() == 0);
}
SUBCASE("get_variables") {
CHECK(base_clazz_1_type.get_variables().size() == 1);
CHECK(base_clazz_2_type.get_variables().size() == 1);
CHECK(derived_clazz_type.get_variables().size() == 1);
CHECK(final_derived_clazz_type.get_variables().size() == 0);
}
SUBCASE("is_base_of") {
{
CHECK_FALSE(base_clazz_1_type.is_base_of<base_clazz_1>());
CHECK_FALSE(base_clazz_1_type.is_base_of(base_clazz_1_type));
CHECK_FALSE(base_clazz_1_type.is_base_of<base_clazz_2>());
CHECK_FALSE(base_clazz_1_type.is_base_of(base_clazz_2_type));
CHECK(base_clazz_1_type.is_base_of<derived_clazz>());
CHECK(base_clazz_1_type.is_base_of(derived_clazz_type));
CHECK(base_clazz_1_type.is_base_of<final_derived_clazz>());
CHECK(base_clazz_1_type.is_base_of(final_derived_clazz_type));
}
{
CHECK_FALSE(base_clazz_2_type.is_base_of<base_clazz_1>());
CHECK_FALSE(base_clazz_2_type.is_base_of(base_clazz_1_type));
CHECK_FALSE(base_clazz_2_type.is_base_of<base_clazz_2>());
CHECK_FALSE(base_clazz_2_type.is_base_of(base_clazz_2_type));
CHECK(base_clazz_2_type.is_base_of<derived_clazz>());
CHECK(base_clazz_2_type.is_base_of(derived_clazz_type));
CHECK(base_clazz_2_type.is_base_of<final_derived_clazz>());
CHECK(base_clazz_2_type.is_base_of(final_derived_clazz_type));
}
{
CHECK_FALSE(derived_clazz_type.is_base_of<base_clazz_1>());
CHECK_FALSE(derived_clazz_type.is_base_of(base_clazz_1_type));
CHECK_FALSE(derived_clazz_type.is_base_of<base_clazz_2>());
CHECK_FALSE(derived_clazz_type.is_base_of(base_clazz_2_type));
CHECK_FALSE(derived_clazz_type.is_base_of<derived_clazz>());
CHECK_FALSE(derived_clazz_type.is_base_of(derived_clazz_type));
}
}
SUBCASE("is_derived_from") {
{
CHECK_FALSE(base_clazz_1_type.is_derived_from<base_clazz_1>());
CHECK_FALSE(base_clazz_1_type.is_derived_from(base_clazz_1_type));
CHECK_FALSE(base_clazz_1_type.is_derived_from<base_clazz_2>());
CHECK_FALSE(base_clazz_1_type.is_derived_from(base_clazz_2_type));
CHECK_FALSE(base_clazz_1_type.is_derived_from<derived_clazz>());
CHECK_FALSE(base_clazz_1_type.is_derived_from(derived_clazz_type));
}
{
CHECK_FALSE(base_clazz_2_type.is_derived_from<base_clazz_1>());
CHECK_FALSE(base_clazz_2_type.is_derived_from(base_clazz_1_type));
CHECK_FALSE(base_clazz_2_type.is_derived_from<base_clazz_2>());
CHECK_FALSE(base_clazz_2_type.is_derived_from(base_clazz_2_type));
CHECK_FALSE(base_clazz_2_type.is_derived_from<derived_clazz>());
CHECK_FALSE(base_clazz_2_type.is_derived_from(derived_clazz_type));
}
{
CHECK(derived_clazz_type.is_derived_from<base_clazz_1>());
CHECK(derived_clazz_type.is_derived_from(base_clazz_1_type));
CHECK(derived_clazz_type.is_derived_from<base_clazz_2>());
CHECK(derived_clazz_type.is_derived_from(base_clazz_2_type));
CHECK_FALSE(derived_clazz_type.is_derived_from<derived_clazz>());
CHECK_FALSE(derived_clazz_type.is_derived_from(derived_clazz_type));
}
{
CHECK(final_derived_clazz_type.is_derived_from<base_clazz_1>());
CHECK(final_derived_clazz_type.is_derived_from(base_clazz_1_type));
CHECK(final_derived_clazz_type.is_derived_from<base_clazz_2>());
CHECK(final_derived_clazz_type.is_derived_from(base_clazz_2_type));
CHECK(final_derived_clazz_type.is_derived_from<derived_clazz>());
CHECK(final_derived_clazz_type.is_derived_from(derived_clazz_type));
}
}
SUBCASE("get_function") {
CHECK(base_clazz_1_type.get_function("base_function_1"));
CHECK_FALSE(base_clazz_1_type.get_function("base_function_2"));
CHECK_FALSE(base_clazz_1_type.get_function("derived_function"));
CHECK_FALSE(base_clazz_2_type.get_function("base_function_1"));
CHECK(base_clazz_2_type.get_function("base_function_2"));
CHECK_FALSE(base_clazz_2_type.get_function("derived_function"));
CHECK(derived_clazz_type.get_function("base_function_1"));
CHECK(derived_clazz_type.get_function("base_function_2"));
CHECK(derived_clazz_type.get_function("derived_function"));
}
SUBCASE("get_member") {
CHECK(base_clazz_1_type.get_member("base_member_1"));
CHECK_FALSE(base_clazz_1_type.get_member("base_member_2"));
CHECK_FALSE(base_clazz_1_type.get_member("derived_member"));
CHECK_FALSE(base_clazz_2_type.get_member("base_member_1"));
CHECK(base_clazz_2_type.get_member("base_member_2"));
CHECK_FALSE(base_clazz_2_type.get_member("derived_member"));
CHECK(derived_clazz_type.get_member("base_member_1"));
CHECK(derived_clazz_type.get_member("base_member_2"));
CHECK(derived_clazz_type.get_member("derived_member"));
}
SUBCASE("get_method") {
CHECK(base_clazz_1_type.get_method("base_method_1"));
CHECK_FALSE(base_clazz_1_type.get_method("base_method_2"));
CHECK_FALSE(base_clazz_1_type.get_method("derived_method"));
CHECK_FALSE(base_clazz_2_type.get_method("base_method_1"));
CHECK(base_clazz_2_type.get_method("base_method_2"));
CHECK_FALSE(base_clazz_2_type.get_method("derived_method"));
CHECK(derived_clazz_type.get_method("base_method_1"));
CHECK(derived_clazz_type.get_method("base_method_2"));
CHECK(derived_clazz_type.get_method("derived_method"));
}
SUBCASE("get_variable") {
CHECK(base_clazz_1_type.get_variable("base_variable_1"));
CHECK_FALSE(base_clazz_1_type.get_variable("base_variable_2"));
CHECK_FALSE(base_clazz_1_type.get_variable("derived_variable"));
CHECK_FALSE(base_clazz_2_type.get_variable("base_variable_1"));
CHECK(base_clazz_2_type.get_variable("base_variable_2"));
CHECK_FALSE(base_clazz_2_type.get_variable("derived_variable"));
CHECK(derived_clazz_type.get_variable("base_variable_1"));
CHECK(derived_clazz_type.get_variable("base_variable_2"));
CHECK(derived_clazz_type.get_variable("derived_variable"));
}
SUBCASE("get_constructor_with") {
{
CHECK_FALSE(base_clazz_1_type.get_constructor_with<>());
CHECK(base_clazz_1_type.get_constructor_with<int>());
CHECK_FALSE(base_clazz_1_type.get_constructor_with<float>());
}
{
CHECK_FALSE(base_clazz_2_type.get_constructor_with<>());
CHECK_FALSE(base_clazz_2_type.get_constructor_with<int>());
CHECK(base_clazz_2_type.get_constructor_with<float>());
}
{
CHECK_FALSE(derived_clazz_type.get_constructor_with<>());
CHECK_FALSE(derived_clazz_type.get_constructor_with<int>());
CHECK_FALSE(derived_clazz_type.get_constructor_with<float>());
CHECK(derived_clazz_type.get_constructor_with<int, float>());
CHECK_FALSE(derived_clazz_type.get_constructor_with<float, int>());
}
}
SUBCASE("get_function_with") {
CHECK(base_clazz_1_type.get_function("base_function_1_overloaded"));
{
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK(base_clazz_1_type.get_function_with<int>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<int, float>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<float>("base_function_1_overloaded"));
CHECK(base_clazz_1_type.get_function_with<int, int>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<float, float>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<double>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with<double, double>("base_function_1_overloaded"));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK(base_clazz_1_type.get_function_with("base_function_1_overloaded", {int_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", {int_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", {float_type}));
CHECK(base_clazz_1_type.get_function_with("base_function_1_overloaded", {int_type, int_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", {float_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", {double_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", {double_type, double_type}));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{int_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{int_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{float_type}));
CHECK(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{int_type, int_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{float_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with<>("base_function_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{double_type}));
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", meta::any_type_list{double_type, double_type}));
}
}
SUBCASE("get_method_with") {
CHECK(base_clazz_1_type.get_method("base_method_1_overloaded"));
{
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with<int>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<int, int>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with<float>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<float, float>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<double>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with<double, double>("base_method_1_overloaded"));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with("base_method_1_overloaded", {int_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", {int_type, int_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with("base_method_1_overloaded", {float_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", {float_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", {double_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", {double_type, double_type}));
}
{
meta::number_type int_type = meta::resolve_type<int>();
meta::number_type float_type = meta::resolve_type<float>();
meta::number_type double_type = meta::resolve_type<double>();
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{int_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{int_type, int_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded"));
CHECK(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{float_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{float_type, float_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with<>("base_method_1_overloaded"));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{double_type}));
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", meta::any_type_list{double_type, double_type}));
}
}
}

View File

@@ -0,0 +1,164 @@
/*******************************************************************************
* 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
{
enum class color : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
white = red | green | blue,
};
enum ecolor : int {
ecolor_red = 0xFF0000,
ecolor_green = 0x00FF00,
ecolor_blue = 0x0000FF,
ecolor_white = ecolor_red | ecolor_green | ecolor_blue,
};
}
TEST_CASE("meta/meta_types/enum_type") {
namespace meta = meta_hpp;
meta::enum_<color>()
.evalue_("red", color::red)
.evalue_("green", color::green)
.evalue_("blue", color::blue)
.evalue_("white", color::white);
meta::enum_<ecolor>()
.evalue_("red", ecolor_red)
.evalue_("green", ecolor_green)
.evalue_("blue", ecolor_blue)
.evalue_("white", ecolor_white);
SUBCASE("color") {
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
CHECK(color_type.get_id() == meta::resolve_type(color{}).get_id());
CHECK(color_type.get_flags() == meta::enum_flags::is_scoped);
CHECK(color_type.get_underlying_type() == meta::resolve_type<unsigned>());
CHECK(color_type.get_evalues().size() == 4);
}
SUBCASE("ecolor") {
const meta::enum_type ecolor_type = meta::resolve_type<ecolor>();
REQUIRE(ecolor_type);
CHECK(ecolor_type.get_id() == meta::resolve_type(ecolor{}).get_id());
CHECK(ecolor_type.get_flags() == meta::enum_flags{});
CHECK(ecolor_type.get_underlying_type() == meta::resolve_type<int>());
CHECK(ecolor_type.get_evalues().size() == 4);
}
SUBCASE("const color") {
const meta::enum_type color_type = meta::resolve_type<const color>();
REQUIRE(color_type);
CHECK(color_type.get_id() == meta::resolve_type(color{}).get_id());
CHECK(color_type.get_flags() == meta::enum_flags::is_scoped);
CHECK(color_type.get_underlying_type() == meta::resolve_type<unsigned>());
CHECK(color_type.get_evalues().size() == 4);
}
SUBCASE("const ecolor") {
const meta::enum_type ecolor_type = meta::resolve_type<const ecolor>();
REQUIRE(ecolor_type);
CHECK(ecolor_type.get_id() == meta::resolve_type(ecolor{}).get_id());
CHECK(ecolor_type.get_flags() == meta::enum_flags{});
CHECK(ecolor_type.get_underlying_type() == meta::resolve_type<int>());
CHECK(ecolor_type.get_evalues().size() == 4);
}
SUBCASE("color/get_evalue") {
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
{
const meta::evalue green_value = color_type.get_evalue("green");
REQUIRE(green_value);
CHECK(green_value.get_value() == color::green);
CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(color::green));
}
{
const meta::evalue yellow_value = color_type.get_evalue("yellow");
CHECK_FALSE(yellow_value);
}
}
SUBCASE("ecolor/get_evalue") {
const meta::enum_type ecolor_type = meta::resolve_type<ecolor>();
REQUIRE(ecolor_type);
{
const meta::evalue green_value = ecolor_type.get_evalue("green");
REQUIRE(green_value);
CHECK(green_value.get_value() == ecolor_green);
CHECK(green_value.get_underlying_value() == meta::detail::to_underlying(ecolor_green));
}
{
const meta::evalue yellow_value = ecolor_type.get_evalue("yellow");
CHECK_FALSE(yellow_value);
}
}
SUBCASE("color/value_to_name") {
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
CHECK(color_type.value_to_name(color::red) == "red");
CHECK(color_type.value_to_name(color::blue) == "blue");
CHECK(color_type.value_to_name(color{100500}).empty());
}
SUBCASE("ecolor/value_to_name") {
const meta::enum_type ecolor_type = meta::resolve_type<ecolor>();
REQUIRE(ecolor_type);
CHECK(ecolor_type.value_to_name(ecolor_red) == "red");
CHECK(ecolor_type.value_to_name(ecolor_blue) == "blue");
CHECK(ecolor_type.value_to_name(ecolor{100500}).empty());
}
SUBCASE("color/name_to_value") {
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
{
REQUIRE(color_type.name_to_value("blue"));
CHECK(color_type.name_to_value("blue") == color::blue);
}
{
REQUIRE_FALSE(color_type.name_to_value("yellow"));
}
}
SUBCASE("ecolor/name_to_value") {
const meta::enum_type ecolor_type = meta::resolve_type<ecolor>();
REQUIRE(ecolor_type);
{
REQUIRE(ecolor_type.name_to_value("blue"));
CHECK(ecolor_type.name_to_value("blue") == ecolor_blue);
}
{
REQUIRE_FALSE(ecolor_type.name_to_value("yellow"));
}
}
}

View File

@@ -0,0 +1,121 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
};
void arg_copy(ivec2) {}
void arg_ref_noexcept(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") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::function_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("arg_copy") {
const meta::function_type type = meta::resolve_type(&arg_copy);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&arg_copy).get_id());
CHECK(type.get_flags() == meta::function_flags{});
CHECK(type.get_arity() == 1);
CHECK(type.get_return_type() == meta::resolve_type<void>());
CHECK(type.get_argument_types() == meta::any_type_list{meta::resolve_type<ivec2>()});
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2>());
CHECK_FALSE(type.get_argument_type(1));
}
SUBCASE("arg_ref_noexcept") {
const meta::function_type type = meta::resolve_type(&arg_ref_noexcept);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&arg_ref_noexcept).get_id());
CHECK(type.get_flags() == meta::function_flags::is_noexcept);
CHECK(type.get_argument_types() == meta::any_type_list{meta::resolve_type<ivec2&>()});
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2&>());
CHECK_FALSE(type.get_argument_type(1));
}
SUBCASE("arg_cref_noexcept") {
const meta::function_type type = meta::resolve_type(&arg_cref_noexcept);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&arg_cref_noexcept).get_id());
CHECK(type.get_flags() == meta::function_flags::is_noexcept);
CHECK(type.get_argument_types() == meta::any_type_list{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_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() == meta::any_type_list{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() == meta::any_type_list{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() == meta::any_type_list{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() == meta::any_type_list{meta::resolve_type<const ivec2*>()});
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2*>());
CHECK_FALSE(type.get_argument_type(1));
}
}

View File

@@ -0,0 +1,47 @@
/*******************************************************************************
* 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 clazz_1 {
int int_member = 1;
const int const_int_member = 2;
};
}
TEST_CASE("meta/meta_types/member_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::member_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("int") {
const meta::member_type type = meta::resolve_type(&clazz_1::int_member);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&clazz_1::int_member).get_id());
CHECK(type.get_flags() == meta::member_flags{});
CHECK(type.get_owner_type() == meta::resolve_type<clazz_1>());
CHECK(type.get_value_type() == meta::resolve_type<int>());
}
SUBCASE("const int") {
const meta::member_type type = meta::resolve_type(&clazz_1::const_int_member);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&clazz_1::const_int_member).get_id());
CHECK(type.get_flags() == meta::member_flags::is_readonly);
CHECK(type.get_owner_type() == meta::resolve_type<clazz_1>());
CHECK(type.get_value_type() == meta::resolve_type<int>());
}
}

View File

@@ -0,0 +1,68 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
int& at(std::size_t i) {
switch ( i ) {
case 0: return x;
case 1: return y;
default: throw std::out_of_range("ivec2::at");
}
}
int length2() const noexcept {
return x * x + y * y;
}
};
}
TEST_CASE("meta/meta_types/method_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::method_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("ivec2::at") {
const meta::method_type type = meta::resolve_type(&ivec2::at);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&ivec2::at).get_id());
CHECK(type.get_flags() == meta::method_flags{});
CHECK(type.get_arity() == 1);
CHECK(type.get_owner_type() == meta::resolve_type<ivec2>());
CHECK(type.get_return_type() == meta::resolve_type<int&>());
CHECK(type.get_argument_types() == meta::any_type_list{meta::resolve_type<std::size_t>()});
CHECK(type.get_argument_type(0) == meta::resolve_type<std::size_t>());
CHECK_FALSE(type.get_argument_type(1));
}
SUBCASE("ivec2::length2") {
const meta::method_type type = meta::resolve_type(&ivec2::length2);
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type(&ivec2::length2).get_id());
CHECK(type.get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept));
CHECK(type.get_arity() == 0);
CHECK(type.get_owner_type() == meta::resolve_type<ivec2>());
CHECK(type.get_return_type() == meta::resolve_type<int>());
CHECK(type.get_argument_types() == meta::any_type_list{});
CHECK_FALSE(type.get_argument_type(0));
}
}

View File

@@ -0,0 +1,54 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_types/number_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::number_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("int") {
const meta::number_type type = meta::resolve_type<int>();
REQUIRE(type);
CHECK(type.get_size() == sizeof(int));
CHECK(type.get_align() == alignof(int));
CHECK(type.get_flags() == (
meta::number_flags::is_signed |
meta::number_flags::is_integral));
}
SUBCASE("const float") {
const meta::number_type type = meta::resolve_type<const float>();
REQUIRE(type);
CHECK(type.get_size() == sizeof(float));
CHECK(type.get_align() == alignof(float));
CHECK(type.get_flags() == (
meta::number_flags::is_signed |
meta::number_flags::is_floating_point));
}
SUBCASE("const unsigned long long") {
const meta::number_type type = meta::resolve_type<const unsigned long long>();
REQUIRE(type);
CHECK(type.get_size() == sizeof(unsigned long long));
CHECK(type.get_align() == alignof(unsigned long long));
CHECK(type.get_flags() == (
meta::number_flags::is_unsigned |
meta::number_flags::is_integral));
}
}

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_types/pointer_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::pointer_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("int*") {
const meta::pointer_type type = meta::resolve_type<int*>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<int*>().get_id());
CHECK(type.get_flags() == meta::pointer_flags{});
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("const int* const") {
const meta::pointer_type type = meta::resolve_type<const int* const>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<const int*>().get_id());
CHECK(type.get_flags() == meta::pointer_flags::is_readonly);
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("int**") {
const meta::pointer_type type = meta::resolve_type<int**>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<int**>().get_id());
CHECK(type.get_flags() == meta::pointer_flags{});
CHECK(type.get_data_type() == meta::resolve_type<int*>());
}
SUBCASE("const int* const*") {
const meta::pointer_type type = meta::resolve_type<const int* const*>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<const int* const*>().get_id());
CHECK(type.get_flags() == meta::pointer_flags::is_readonly);
CHECK(type.get_data_type() == meta::resolve_type<const int*>());
}
}

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_types/reference_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::reference_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("int&") {
const meta::reference_type type = meta::resolve_type<int&>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<int&>().get_id());
CHECK(type.get_flags() == (meta::reference_flags::is_lvalue));
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("const int&") {
const meta::reference_type type = meta::resolve_type<const int&>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<const int&>().get_id());
CHECK(type.get_flags() == (meta::reference_flags::is_readonly | meta::reference_flags::is_lvalue));
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("int&&") {
const meta::reference_type type = meta::resolve_type<int&&>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<int&&>().get_id());
CHECK(type.get_flags() == (meta::reference_flags::is_rvalue));
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
SUBCASE("const int&&") {
const meta::reference_type type = meta::resolve_type<const int&&>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<const int&&>().get_id());
CHECK(type.get_flags() == (meta::reference_flags::is_readonly | meta::reference_flags::is_rvalue));
CHECK(type.get_data_type() == meta::resolve_type<int>());
}
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************
* 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
{
}
TEST_CASE("meta/meta_types/void_type") {
namespace meta = meta_hpp;
SUBCASE("") {
const meta::void_type type;
CHECK_FALSE(type);
CHECK_FALSE(type.is_valid());
}
SUBCASE("void") {
const meta::void_type type = meta::resolve_type<void>();
REQUIRE(type);
CHECK(type.get_id() == meta::resolve_type<void>().get_id());
}
SUBCASE("void*") {
void* ptr{};
const meta::pointer_type ptr_type = meta::resolve_type(ptr);
CHECK(ptr_type == meta::resolve_type<void*>());
CHECK_FALSE(ptr_type.get_flags().has(meta::pointer_flags::is_readonly));
CHECK(ptr_type.get_data_type() == meta::resolve_type<void>());
}
SUBCASE("const void*") {
const void* ptr{};
const meta::pointer_type ptr_type = meta::resolve_type(ptr);
CHECK(ptr_type == meta::resolve_type<const void*>());
CHECK(ptr_type.get_flags().has(meta::pointer_flags::is_readonly));
CHECK(ptr_type.get_data_type() == meta::resolve_type<void>());
}
}

View File

@@ -0,0 +1,11 @@
/*******************************************************************************
* 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"
TEST_CASE("meta_hpp") {
namespace meta = meta_hpp;
}

View File

@@ -0,0 +1,11 @@
/*******************************************************************************
* 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.hpp/meta_all.hpp>
#include <doctest/doctest.h>
#include <iostream>
#include <sstream>

View File

@@ -0,0 +1,352 @@
/*******************************************************************************
* 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;
[[maybe_unused]] A(A&&) noexcept { ++move_ctors_; }
[[maybe_unused]] A(const A&) { ++copy_ctors_; }
A& operator=(A&&) = delete;
A& operator=(const A&) = delete;
int i = 1;
[[maybe_unused, nodiscard]] int f() const { return i; }
static int copy_ctors_;
static int move_ctors_;
};
int A::copy_ctors_{};
int A::move_ctors_{};
struct B : virtual A {
int bi = 2;
[[maybe_unused, nodiscard]] int f() const { return bi; }
};
struct C : virtual A {
int ci = 3;
[[maybe_unused, nodiscard]] int f() const { return ci; }
};
struct D : B, C {
int di = 4;
[[maybe_unused, nodiscard]] int f() const { return di; }
};
}
TEST_CASE("meta/meta_utilities/arg2") {
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/arg2/cast") {
namespace meta = meta_hpp;
using meta::detail::uarg;
auto LV = []() -> D& { static D v; return v; };
auto CLV = []() -> const D& { static D v; return v; };
auto XV = []() -> D&& { static D v; return std::move(v); };
auto CXV = []() -> const D&& { static D v; return std::move(v); };
auto PRV = []() -> D { return D{}; };
auto CPRV = []() -> const D { return D{}; };
auto LV_PTR = []() -> D*& { static D v; static D* p{&v}; return p; };
auto LV_CPTR = []() -> const D*& { static D v; static const D* p{&v}; return p; };
auto CLV_PTR = []() -> D* const& { static D v; static D* p{&v}; return p; };
auto CLV_CPTR = []() -> const D* const& { static D v; static const D* p{&v}; return p; };
auto XV_PTR = []() -> D*&& { static D v; static D* p{&v}; return std::move(p); };
auto XV_CPTR = []() -> const D*&& { static D v; static const D* p{&v}; return std::move(p); };
auto CXV_PTR = []() -> D* const&& { static D v; static D* p{&v}; return std::move(p); };
auto CXV_CPTR = []() -> const D* const&& { static D v; static const D* p{&v}; return std::move(p); };
auto PRV_PTR = []() -> D* { static D v; static D* p{&v}; return p; };
auto PRV_CPTR = []() -> const D* { static D v; static const D* p{&v}; return p; };
// *------------------------------------------------------------*
// | ======> | T, const T | T& | const T& | T&& | const T&& |
// |---------*------------*------*----------*------*------------|
// | LV | Cc | ++ | ++ | | |
// |---------*------------*------*----------*------*------------|
// | CLV | Cc | | ++ | | |
// |---------*------------*------*----------*------*------------|
// | XV | Mc | | ++ | ++ | ++ |
// |---------*------------*------*----------*------*------------|
// | CXV | Cc | | ++ | | ++ |
// |---------*------------*------*----------*------*------------|
// | PRV | ++ | | ++ | ++ | ++ |
// |---------*------------*------*----------*------*------------|
// | CPRV | ++ | | ++ | | ++ |
// *------------------------------------------------------------*
A::copy_ctors_ = 0;
A::move_ctors_ = 0;
SUBCASE("LV") {
CHECK(uarg{LV()}.can_cast_to<A>());
CHECK(uarg{LV()}.can_cast_to<const A>());
CHECK(uarg{LV()}.can_cast_to<A&>());
CHECK(uarg{LV()}.can_cast_to<const A&>());
CHECK_FALSE(uarg{LV()}.can_cast_to<A&&>());
CHECK_FALSE(uarg{LV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{LV()}.cast<A>().f() == 1);
CHECK(uarg{LV()}.cast<const A>().f() == 1);
CHECK(uarg{LV()}.cast<A&>().f() == 1);
CHECK(uarg{LV()}.cast<const A&>().f() == 1);
CHECK_THROWS(std::ignore = uarg{LV()}.cast<A&&>());
CHECK_THROWS(std::ignore = uarg{LV()}.cast<const A&&>());
CHECK(A::copy_ctors_ == 2);
CHECK(A::move_ctors_ == 0);
}
SUBCASE("CLV") {
CHECK(uarg{CLV()}.can_cast_to<A>());
CHECK(uarg{CLV()}.can_cast_to<const A>());
CHECK_FALSE(uarg{CLV()}.can_cast_to<A&>());
CHECK(uarg{CLV()}.can_cast_to<const A&>());
CHECK_FALSE(uarg{CLV()}.can_cast_to<A&&>());
CHECK_FALSE(uarg{CLV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{CLV()}.cast<A>().f() == 1);
CHECK(uarg{CLV()}.cast<const A>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CLV()}.cast<A&>());
CHECK(uarg{CLV()}.cast<const A&>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CLV()}.cast<A&&>());
CHECK_THROWS(std::ignore = uarg{CLV()}.cast<const A&&>());
CHECK(A::copy_ctors_ == 2);
CHECK(A::move_ctors_ == 0);
}
SUBCASE("XV") {
CHECK(uarg{XV()}.can_cast_to<A>());
CHECK(uarg{XV()}.can_cast_to<const A>());
CHECK_FALSE(uarg{XV()}.can_cast_to<A&>());
CHECK(uarg{XV()}.can_cast_to<const A&>());
CHECK(uarg{XV()}.can_cast_to<A&&>());
CHECK(uarg{XV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{XV()}.cast<A>().f() == 1);
CHECK(uarg{XV()}.cast<const A>().f() == 1);
CHECK_THROWS(std::ignore = uarg{XV()}.cast<A&>());
CHECK(uarg{XV()}.cast<const A&>().f() == 1);
CHECK(uarg{XV()}.cast<A&&>().f() == 1);
CHECK(uarg{XV()}.cast<const A&&>().f() == 1);
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 2);
}
SUBCASE("CXV") {
CHECK(uarg{CXV()}.can_cast_to<A>());
CHECK(uarg{CXV()}.can_cast_to<const A>());
CHECK_FALSE(uarg{CXV()}.can_cast_to<A&>());
CHECK(uarg{CXV()}.can_cast_to<const A&>());
CHECK_FALSE(uarg{CXV()}.can_cast_to<A&&>());
CHECK(uarg{CXV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{CXV()}.cast<A>().f() == 1);
CHECK(uarg{CXV()}.cast<const A>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CXV()}.cast<A&>());
CHECK(uarg{CXV()}.cast<const A&>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CXV()}.cast<A&&>());
CHECK(uarg{CXV()}.cast<const A&&>().f() == 1);
CHECK(A::copy_ctors_ == 2);
CHECK(A::move_ctors_ == 0);
}
SUBCASE("PRV") {
CHECK(uarg{PRV()}.can_cast_to<A>());
CHECK(uarg{PRV()}.can_cast_to<const A>());
CHECK_FALSE(uarg{PRV()}.can_cast_to<A&>());
CHECK(uarg{PRV()}.can_cast_to<const A&>());
CHECK(uarg{PRV()}.can_cast_to<A&&>());
CHECK(uarg{PRV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{PRV()}.cast<A>().f() == 1);
CHECK(uarg{PRV()}.cast<const A>().f() == 1);
CHECK_THROWS(std::ignore = uarg{PRV()}.cast<A&>());
CHECK(uarg{PRV()}.cast<const A&>().f() == 1);
CHECK(uarg{PRV()}.cast<A&&>().f() == 1);
CHECK(uarg{PRV()}.cast<const A&&>().f() == 1);
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 2);
}
SUBCASE("CPRV") {
CHECK(uarg{CPRV()}.can_cast_to<A>());
CHECK(uarg{CPRV()}.can_cast_to<const A>());
CHECK_FALSE(uarg{CPRV()}.can_cast_to<A&>());
CHECK(uarg{CPRV()}.can_cast_to<const A&>());
CHECK_FALSE(uarg{CPRV()}.can_cast_to<A&&>());
CHECK(uarg{CPRV()}.can_cast_to<const A&&>());
CHECK(A::copy_ctors_ == 0);
CHECK(A::move_ctors_ == 0);
CHECK(uarg{CPRV()}.cast<A>().f() == 1);
CHECK(uarg{CPRV()}.cast<const A>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CPRV()}.cast<A&>());
CHECK(uarg{CPRV()}.cast<const A&>().f() == 1);
CHECK_THROWS(std::ignore = uarg{CPRV()}.cast<A&&>());
CHECK(uarg{CPRV()}.cast<const A&&>().f() == 1);
CHECK(A::copy_ctors_ == 2);
CHECK(A::move_ctors_ == 0);
}
SUBCASE("LV_PTR") {
CHECK(uarg{LV_PTR()}.can_cast_to<A*>());
CHECK(uarg{LV_PTR()}.can_cast_to<A* const>());
CHECK(uarg{LV_PTR()}.can_cast_to<const A*>());
CHECK(uarg{LV_PTR()}.can_cast_to<const A* const>());
CHECK(uarg{LV_PTR()}.cast<A*>()->f() == 1);
CHECK(uarg{LV_PTR()}.cast<A* const>()->f() == 1);
CHECK(uarg{LV_PTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{LV_PTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("LV_CPTR") {
CHECK_FALSE(uarg{LV_CPTR()}.can_cast_to<A*>());
CHECK_FALSE(uarg{LV_CPTR()}.can_cast_to<A* const>());
CHECK(uarg{LV_CPTR()}.can_cast_to<const A*>());
CHECK(uarg{LV_CPTR()}.can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg{LV_CPTR()}.cast<A*>());
CHECK_THROWS(std::ignore = uarg{LV_CPTR()}.cast<A* const>());
CHECK(uarg{LV_CPTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{LV_CPTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("CLV_PTR") {
CHECK(uarg{CLV_PTR()}.can_cast_to<A*>());
CHECK(uarg{CLV_PTR()}.can_cast_to<A* const>());
CHECK(uarg{CLV_PTR()}.can_cast_to<const A*>());
CHECK(uarg{CLV_PTR()}.can_cast_to<const A* const>());
CHECK(uarg{CLV_PTR()}.cast<A*>()->f() == 1);
CHECK(uarg{CLV_PTR()}.cast<A* const>()->f() == 1);
CHECK(uarg{CLV_PTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{CLV_PTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("CLV_CPTR") {
CHECK_FALSE(uarg{CLV_CPTR()}.can_cast_to<A*>());
CHECK_FALSE(uarg{CLV_CPTR()}.can_cast_to<A* const>());
CHECK(uarg{CLV_CPTR()}.can_cast_to<const A*>());
CHECK(uarg{CLV_CPTR()}.can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg{CLV_CPTR()}.cast<A*>());
CHECK_THROWS(std::ignore = uarg{CLV_CPTR()}.cast<A* const>());
CHECK(uarg{CLV_CPTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{CLV_CPTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("XV_PTR") {
CHECK(uarg{XV_PTR()}.can_cast_to<A*>());
CHECK(uarg{XV_PTR()}.can_cast_to<A* const>());
CHECK(uarg{XV_PTR()}.can_cast_to<const A*>());
CHECK(uarg{XV_PTR()}.can_cast_to<const A* const>());
CHECK(uarg{XV_PTR()}.cast<A*>()->f() == 1);
CHECK(uarg{XV_PTR()}.cast<A* const>()->f() == 1);
CHECK(uarg{XV_PTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{XV_PTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("XV_CPTR") {
CHECK_FALSE(uarg{XV_CPTR()}.can_cast_to<A*>());
CHECK_FALSE(uarg{XV_CPTR()}.can_cast_to<A* const>());
CHECK(uarg{XV_CPTR()}.can_cast_to<const A*>());
CHECK(uarg{XV_CPTR()}.can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg{XV_CPTR()}.cast<A*>());
CHECK_THROWS(std::ignore = uarg{XV_CPTR()}.cast<A* const>());
CHECK(uarg{XV_CPTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{XV_CPTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("CXV_PTR") {
CHECK(uarg{CXV_PTR()}.can_cast_to<A*>());
CHECK(uarg{CXV_PTR()}.can_cast_to<A* const>());
CHECK(uarg{CXV_PTR()}.can_cast_to<const A*>());
CHECK(uarg{CXV_PTR()}.can_cast_to<const A* const>());
CHECK(uarg{CXV_PTR()}.cast<A*>()->f() == 1);
CHECK(uarg{CXV_PTR()}.cast<A* const>()->f() == 1);
CHECK(uarg{CXV_PTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{CXV_PTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("CXV_CPTR") {
CHECK_FALSE(uarg{CXV_CPTR()}.can_cast_to<A*>());
CHECK_FALSE(uarg{CXV_CPTR()}.can_cast_to<A* const>());
CHECK(uarg{CXV_CPTR()}.can_cast_to<const A*>());
CHECK(uarg{CXV_CPTR()}.can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg{CXV_CPTR()}.cast<A*>());
CHECK_THROWS(std::ignore = uarg{CXV_CPTR()}.cast<A* const>());
CHECK(uarg{CXV_CPTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{CXV_CPTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("PRV_PTR") {
CHECK(uarg{PRV_PTR()}.can_cast_to<A*>());
CHECK(uarg{PRV_PTR()}.can_cast_to<A* const>());
CHECK(uarg{PRV_PTR()}.can_cast_to<const A*>());
CHECK(uarg{PRV_PTR()}.can_cast_to<const A* const>());
CHECK(uarg{PRV_PTR()}.cast<A*>()->f() == 1);
CHECK(uarg{PRV_PTR()}.cast<A* const>()->f() == 1);
CHECK(uarg{PRV_PTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{PRV_PTR()}.cast<const A* const>()->f() == 1);
}
SUBCASE("PRV_CPTR") {
CHECK_FALSE(uarg{PRV_CPTR()}.can_cast_to<A*>());
CHECK_FALSE(uarg{PRV_CPTR()}.can_cast_to<A* const>());
CHECK(uarg{PRV_CPTR()}.can_cast_to<const A*>());
CHECK(uarg{PRV_CPTR()}.can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg{PRV_CPTR()}.cast<A*>());
CHECK_THROWS(std::ignore = uarg{PRV_CPTR()}.cast<A* const>());
CHECK(uarg{PRV_CPTR()}.cast<const A*>()->f() == 1);
CHECK(uarg{PRV_CPTR()}.cast<const A* const>()->f() == 1);
}
}

View File

@@ -0,0 +1,127 @@
/*******************************************************************************
* 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;
[[maybe_unused, nodiscard]] int f() const { return i; }
};
struct B : virtual A {
int bi = 2;
[[maybe_unused, nodiscard]] int f() const { return bi; }
};
struct C : virtual A {
int ci = 3;
[[maybe_unused, nodiscard]] int f() const { return ci; }
};
struct D : B, C {
int di = 4;
[[maybe_unused, nodiscard]] int f() const { return di; }
};
}
TEST_CASE("meta/meta_utilities/arg3") {
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/arg3/cast") {
namespace meta = meta_hpp;
using meta::detail::uarg;
auto LV = []() -> D& { static D v; return v; };
auto CLV = []() -> const D& { static D v; return v; };
auto XV = []() -> D&& { static D v; return std::move(v); };
auto CXV = []() -> const D&& { static D v; return std::move(v); };
auto PRV = []() -> D { return D{}; };
auto CPRV = []() -> const D { return D{}; };
// *------------------------------------------------------------*
// | ======> | T, const T | T& | const T& | T&& | const T&& |
// |---------*------------*------*----------*------*------------|
// | LV | Cc | ++ | ++ | | |
// |---------*------------*------*----------*------*------------|
// | CLV | Cc | | ++ | | |
// |---------*------------*------*----------*------*------------|
// | XV | Mc | | ++ | ++ | ++ |
// |---------*------------*------*----------*------*------------|
// | CXV | Cc | | ++ | | ++ |
// |---------*------------*------*----------*------*------------|
// | PRV | ++ | | ++ | ++ | ++ |
// |---------*------------*------*----------*------*------------|
// | CPRV | ++ | | ++ | | ++ |
// *------------------------------------------------------------*
SUBCASE("LV") {
CHECK_FALSE(uarg{LV()}.can_cast_to<A>());
CHECK_FALSE(uarg{LV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{LV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{LV()}.cast<const A>());
}
SUBCASE("CLV") {
CHECK_FALSE(uarg{CLV()}.can_cast_to<A>());
CHECK_FALSE(uarg{CLV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{CLV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{CLV()}.cast<const A>());
}
SUBCASE("XV") {
CHECK_FALSE(uarg{XV()}.can_cast_to<A>());
CHECK_FALSE(uarg{XV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{XV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{XV()}.cast<const A>());
}
SUBCASE("CXV") {
CHECK_FALSE(uarg{CXV()}.can_cast_to<A>());
CHECK_FALSE(uarg{CXV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{CXV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{CXV()}.cast<const A>());
}
SUBCASE("PRV") {
CHECK_FALSE(uarg{PRV()}.can_cast_to<A>());
CHECK_FALSE(uarg{PRV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{PRV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{PRV()}.cast<const A>());
}
SUBCASE("CPRV") {
CHECK_FALSE(uarg{CPRV()}.can_cast_to<A>());
CHECK_FALSE(uarg{CPRV()}.can_cast_to<const A>());
CHECK_THROWS(std::ignore = uarg{CPRV()}.cast<A>());
CHECK_THROWS(std::ignore = uarg{CPRV()}.cast<const A>());
}
}

View File

@@ -0,0 +1,144 @@
/*******************************************************************************
* 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"
TEST_CASE("meta/meta_utilities/arg4/cast") {
namespace meta = meta_hpp;
using meta::detail::uarg;
auto LV_PTR = []() -> int*& { static int v{42}; static int* p{&v}; return p; };
auto CLV_PTR = []() -> int* const& { static int v{42}; static int* p{&v}; return p; };
auto XV_PTR = []() -> int*&& { static int v{42}; static int* p{&v}; return std::move(p); };
auto CXV_PTR = []() -> int* const&& { static int v{42}; static int* p{&v}; return std::move(p); };
auto PRV_PTR = []() -> int* { static int v{42}; static int* p{&v}; return p; };
auto LV_CPTR = []() -> const int*& { static int v{42}; static const int* p{&v}; return p; };
auto CLV_CPTR = []() -> const int* const& { static int v{42}; static const int* p{&v}; return p; };
auto XV_CPTR = []() -> const int*&& { static int v{42}; static const int* p{&v}; return std::move(p); };
auto CXV_CPTR = []() -> const int* const&& { static int v{42}; static const int* p{&v}; return std::move(p); };
auto PRV_CPTR = []() -> const int* { static int v{42}; static const int* p{&v}; return p; };
SUBCASE("LV_PTR") {
CHECK(uarg{LV_PTR()}.can_cast_to<int*>());
CHECK(uarg{LV_PTR()}.can_cast_to<int* const>());
CHECK(uarg{LV_PTR()}.can_cast_to<const int*>());
CHECK(uarg{LV_PTR()}.can_cast_to<const int* const>());
CHECK(*uarg{LV_PTR()}.cast<int*>() == 42);
CHECK(*uarg{LV_PTR()}.cast<int* const>() == 42);
CHECK(*uarg{LV_PTR()}.cast<const int*>() == 42);
CHECK(*uarg{LV_PTR()}.cast<const int* const>() == 42);
}
SUBCASE("CLV_PTR") {
CHECK(uarg{CLV_PTR()}.can_cast_to<int*>());
CHECK(uarg{CLV_PTR()}.can_cast_to<int* const>());
CHECK(uarg{CLV_PTR()}.can_cast_to<const int*>());
CHECK(uarg{CLV_PTR()}.can_cast_to<const int* const>());
CHECK(*uarg{CLV_PTR()}.cast<int*>() == 42);
CHECK(*uarg{CLV_PTR()}.cast<int* const>() == 42);
CHECK(*uarg{CLV_PTR()}.cast<const int*>() == 42);
CHECK(*uarg{CLV_PTR()}.cast<const int* const>() == 42);
}
SUBCASE("XV_PTR") {
CHECK(uarg{XV_PTR()}.can_cast_to<int*>());
CHECK(uarg{XV_PTR()}.can_cast_to<int* const>());
CHECK(uarg{XV_PTR()}.can_cast_to<const int*>());
CHECK(uarg{XV_PTR()}.can_cast_to<const int* const>());
CHECK(*uarg{XV_PTR()}.cast<int*>() == 42);
CHECK(*uarg{XV_PTR()}.cast<int* const>() == 42);
CHECK(*uarg{XV_PTR()}.cast<const int*>() == 42);
CHECK(*uarg{XV_PTR()}.cast<const int* const>() == 42);
}
SUBCASE("CXV_PTR") {
CHECK(uarg{CXV_PTR()}.can_cast_to<int*>());
CHECK(uarg{CXV_PTR()}.can_cast_to<int* const>());
CHECK(uarg{CXV_PTR()}.can_cast_to<const int*>());
CHECK(uarg{CXV_PTR()}.can_cast_to<const int* const>());
CHECK(*uarg{CXV_PTR()}.cast<int*>() == 42);
CHECK(*uarg{CXV_PTR()}.cast<int* const>() == 42);
CHECK(*uarg{CXV_PTR()}.cast<const int*>() == 42);
CHECK(*uarg{CXV_PTR()}.cast<const int* const>() == 42);
}
SUBCASE("PRV_PTR") {
CHECK(uarg{PRV_PTR()}.can_cast_to<int*>());
CHECK(uarg{PRV_PTR()}.can_cast_to<int* const>());
CHECK(uarg{PRV_PTR()}.can_cast_to<const int*>());
CHECK(uarg{PRV_PTR()}.can_cast_to<const int* const>());
CHECK(*uarg{PRV_PTR()}.cast<int*>() == 42);
CHECK(*uarg{PRV_PTR()}.cast<int* const>() == 42);
CHECK(*uarg{PRV_PTR()}.cast<const int*>() == 42);
CHECK(*uarg{PRV_PTR()}.cast<const int* const>() == 42);
}
SUBCASE("LV_CPTR") {
CHECK_FALSE(uarg{LV_CPTR()}.can_cast_to<int*>());
CHECK_FALSE(uarg{LV_CPTR()}.can_cast_to<int* const>());
CHECK(uarg{LV_CPTR()}.can_cast_to<const int*>());
CHECK(uarg{LV_CPTR()}.can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg{LV_CPTR()}.cast<int*>());
CHECK_THROWS(std::ignore = uarg{LV_CPTR()}.cast<int* const>());
CHECK(*uarg{LV_CPTR()}.cast<const int*>() == 42);
CHECK(*uarg{LV_CPTR()}.cast<const int* const>() == 42);
}
SUBCASE("CLV_CPTR") {
CHECK_FALSE(uarg{CLV_CPTR()}.can_cast_to<int*>());
CHECK_FALSE(uarg{CLV_CPTR()}.can_cast_to<int* const>());
CHECK(uarg{CLV_CPTR()}.can_cast_to<const int*>());
CHECK(uarg{CLV_CPTR()}.can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg{CLV_CPTR()}.cast<int*>());
CHECK_THROWS(std::ignore = uarg{CLV_CPTR()}.cast<int* const>());
CHECK(*uarg{CLV_CPTR()}.cast<const int*>() == 42);
CHECK(*uarg{CLV_CPTR()}.cast<const int* const>() == 42);
}
SUBCASE("XV_CPTR") {
CHECK_FALSE(uarg{XV_CPTR()}.can_cast_to<int*>());
CHECK_FALSE(uarg{XV_CPTR()}.can_cast_to<int* const>());
CHECK(uarg{XV_CPTR()}.can_cast_to<const int*>());
CHECK(uarg{XV_CPTR()}.can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg{XV_CPTR()}.cast<int*>());
CHECK_THROWS(std::ignore = uarg{XV_CPTR()}.cast<int* const>());
CHECK(*uarg{XV_CPTR()}.cast<const int*>() == 42);
CHECK(*uarg{XV_CPTR()}.cast<const int* const>() == 42);
}
SUBCASE("CXV_CPTR") {
CHECK_FALSE(uarg{CXV_CPTR()}.can_cast_to<int*>());
CHECK_FALSE(uarg{CXV_CPTR()}.can_cast_to<int* const>());
CHECK(uarg{CXV_CPTR()}.can_cast_to<const int*>());
CHECK(uarg{CXV_CPTR()}.can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg{CXV_CPTR()}.cast<int*>());
CHECK_THROWS(std::ignore = uarg{CXV_CPTR()}.cast<int* const>());
CHECK(*uarg{CXV_CPTR()}.cast<const int*>() == 42);
CHECK(*uarg{CXV_CPTR()}.cast<const int* const>() == 42);
}
SUBCASE("PRV_CPTR") {
CHECK_FALSE(uarg{PRV_CPTR()}.can_cast_to<int*>());
CHECK_FALSE(uarg{PRV_CPTR()}.can_cast_to<int* const>());
CHECK(uarg{PRV_CPTR()}.can_cast_to<const int*>());
CHECK(uarg{PRV_CPTR()}.can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg{PRV_CPTR()}.cast<int*>());
CHECK_THROWS(std::ignore = uarg{PRV_CPTR()}.cast<int* const>());
CHECK(*uarg{PRV_CPTR()}.cast<const int*>() == 42);
CHECK(*uarg{PRV_CPTR()}.cast<const int* const>() == 42);
}
}

View 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-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_<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::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<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(uarg(arr).can_cast_to<int*>());
CHECK(uarg(arr).can_cast_to<const int*>());
CHECK(uarg(arr).can_cast_to<int* const>());
CHECK(uarg(arr).can_cast_to<const int* const>());
CHECK(uarg(arr).cast<int*>() == static_cast<int*>(arr));
CHECK(uarg(arr).cast<const int*>() == static_cast<const int*>(arr));
CHECK(uarg(arr).cast<int* const>() == static_cast<int*>(arr));
CHECK(uarg(arr).cast<const int* const>() == static_cast<const int*>(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<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(uarg(arr).can_cast_to<int*>());
CHECK(uarg(arr).can_cast_to<const int*>());
CHECK_FALSE(uarg(arr).can_cast_to<int* const>());
CHECK(uarg(arr).can_cast_to<const int* const>());
CHECK_THROWS(std::ignore = uarg(arr).cast<int*>());
CHECK(uarg(arr).cast<const int*>() == static_cast<const int*>(arr));
CHECK_THROWS(std::ignore = uarg(arr).cast<int* const>());
CHECK(uarg(arr).cast<const int* const>() == static_cast<const int*>(arr));
}
SUBCASE("D[2]") {
D arr[2];
CHECK(uarg(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(uarg(arr).can_cast_to<A*>());
CHECK(uarg(arr).can_cast_to<const A*>());
CHECK(uarg(arr).can_cast_to<A* const>());
CHECK(uarg(arr).can_cast_to<const A* const>());
CHECK(uarg(arr).cast<A*>() == static_cast<A*>(arr));
CHECK(uarg(arr).cast<const A*>() == static_cast<const A*>(arr));
CHECK(uarg(arr).cast<A* const>() == static_cast<A*>(arr));
CHECK(uarg(arr).cast<const A* const>() == static_cast<const A*>(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<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(uarg(arr).can_cast_to<A*>());
CHECK(uarg(arr).can_cast_to<const A*>());
CHECK_FALSE(uarg(arr).can_cast_to<A* const>());
CHECK(uarg(arr).can_cast_to<const A* const>());
CHECK_THROWS(std::ignore = uarg(arr).cast<A*>());
CHECK(uarg(arr).cast<const A*>() == static_cast<const A*>(arr));
CHECK_THROWS(std::ignore = uarg(arr).cast<A* const>());
CHECK(uarg(arr).cast<const A* const>() == static_cast<const A*>(arr));
}
SUBCASE("&") {
using T = D[2];
static T src{};
{
auto LV = []() -> T& { return src; };
CHECK(uarg{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(uarg(LV()).cast<A*>() == static_cast<A*>(src));
CHECK(uarg(LV()).cast<const A*>() == static_cast<const A*>(src));
CHECK(uarg(LV()).cast<A* const>() == static_cast<A*>(src));
CHECK(uarg(LV()).cast<const A* const>() == static_cast<const A*>(src));
}
{
auto CLV = []() -> const T& { return src; };
CHECK(uarg{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 = uarg(CLV()).cast<A*>());
CHECK(uarg(CLV()).cast<const A*>() == static_cast<const A*>(src));
CHECK_THROWS(std::ignore = uarg(CLV()).cast<A* const>());
CHECK(uarg(CLV()).cast<const A* const>() == static_cast<const A*>(src));
}
{
auto XV = []() -> T&& { return std::move(src); };
CHECK(uarg{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(uarg(XV()).cast<A*>() == static_cast<A*>(src));
CHECK(uarg(XV()).cast<const A*>() == static_cast<const A*>(src));
CHECK(uarg(XV()).cast<A* const>() == static_cast<A*>(src));
CHECK(uarg(XV()).cast<const A* const>() == static_cast<const A*>(src));
}
{
auto CXV = []() -> const T&& { return std::move(src); };
CHECK(uarg{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 = uarg(CXV()).cast<A*>());
CHECK(uarg(CXV()).cast<const A*>() == static_cast<const A*>(src));
CHECK_THROWS(std::ignore = uarg(CXV()).cast<A* const>());
CHECK(uarg(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(uarg{arr}.can_cast_to<D (&) [2]>());
CHECK(uarg{arr}.can_cast_to<const D (&) [2]>());
CHECK(uarg{&arr}.can_cast_to<D (*) [2]>());
CHECK(uarg{&arr}.can_cast_to<const D (*) [2]>());
CHECK(uarg{&arr}.can_cast_to<D (* const) [2]>());
CHECK(uarg{&arr}.can_cast_to<const D (* const) [2]>());
CHECK(&uarg{arr}.cast<D (&) [2]>() == &arr);
CHECK(&uarg{arr}.cast<const D (&) [2]>() == &arr);
CHECK(uarg{&arr}.cast<D (*) [2]>() == &arr);
CHECK(uarg{&arr}.cast<const D (*) [2]>() == &arr);
CHECK(uarg{&arr}.cast<D (* const) [2]>() == &arr);
CHECK(uarg{&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(uarg{arr}.can_cast_to<D (&) [2]>());
CHECK(uarg{arr}.can_cast_to<const D (&) [2]>());
CHECK_FALSE(uarg{&arr}.can_cast_to<D (*) [2]>());
CHECK(uarg{&arr}.can_cast_to<const D (*) [2]>());
CHECK_FALSE(uarg{&arr}.can_cast_to<D (* const) [2]>());
CHECK(uarg{&arr}.can_cast_to<const D (* const) [2]>());
CHECK_THROWS(std::ignore = &uarg{arr}.cast<D (&) [2]>());
CHECK(&uarg{arr}.cast<const D (&) [2]>() == &arr);
CHECK_THROWS(std::ignore = uarg{&arr}.cast<D (*) [2]>());
CHECK(uarg{&arr}.cast<const D (*) [2]>() == &arr);
CHECK_THROWS(std::ignore = uarg{&arr}.cast<D (* const) [2]>());
CHECK(uarg{&arr}.cast<const D (* const) [2]>() == &arr);
}
}
}

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* 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 base {
base() = default;
base(const base&) = default;
virtual ~base() = default;
virtual int int_method() const = 0;
};
struct clazz : base {
int int_member{42};
int int_method() const override { return int_member; }
};
using int_member_t = int clazz::*;
using int_method_t = int (clazz::*)() const;
int func_with_member(const clazz& cl, int_member_t m) {
return cl.*m;
}
int func_with_method(const clazz& cl, int_method_t m) {
return (cl.*m)();
}
}
TEST_CASE("meta/meta_utilities/arg6") {
namespace meta = meta_hpp;
using meta::detail::uarg;
const meta::scope scope = meta::local_scope_("scope")
.function_("func_with_member", &func_with_member)
.function_("func_with_method", &func_with_method);
SUBCASE("int_member") {
const meta::function f = scope.get_function("func_with_member");
REQUIRE(f);
clazz cl;
CHECK(f.is_invocable_with<clazz&, int_member_t>());
CHECK(f.is_invocable_with(cl, &clazz::int_member));
CHECK(f.invoke(cl, &clazz::int_member) == 42);
CHECK(f.is_invocable_with(meta::uvalue{cl}, meta::uvalue{&clazz::int_member}));
CHECK(f.invoke(meta::uvalue{cl}, meta::uvalue{&clazz::int_member}) == 42);
}
SUBCASE("int_method") {
const meta::function f = scope.get_function("func_with_method");
REQUIRE(f);
clazz cl;
CHECK(f.is_invocable_with<clazz&, int_method_t>());
CHECK(f.is_invocable_with(cl, &clazz::int_method));
CHECK(f.invoke(cl, &clazz::int_method) == 42);
CHECK(f.is_invocable_with(meta::uvalue{cl}, meta::uvalue{&clazz::int_method}));
CHECK(f.invoke(meta::uvalue{cl}, meta::uvalue{&clazz::int_method}) == 42);
}
}

View File

@@ -0,0 +1,196 @@
/*******************************************************************************
* 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/arg7") {
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/arg7/cast/to_void") {
namespace meta = meta_hpp;
using meta::detail::uarg;
SUBCASE("int* -> void*") {
int i{42};
static_assert(std::is_invocable_v<void(void*), int*>);
static_assert(std::is_invocable_v<void(const void*), int*>);
CHECK(uarg{&i}.can_cast_to<void*>());
CHECK(uarg{&i}.can_cast_to<const void*>());
CHECK(uarg{&i}.cast<void*>() == &i);
CHECK(uarg{&i}.cast<const void*>() == &i);
}
SUBCASE("const int* -> void*") {
const int i{42};
static_assert(!std::is_invocable_v<void(void*), const int*>);
static_assert(std::is_invocable_v<void(const void*), const int*>);
CHECK_FALSE(uarg{&i}.can_cast_to<void*>());
CHECK(uarg{&i}.can_cast_to<const void*>());
CHECK_THROWS(std::ignore = uarg{&i}.cast<void*>());
CHECK(uarg{&i}.cast<const void*>() == &i);
}
SUBCASE("D* -> void*") {
D d;
static_assert(std::is_invocable_v<void(void*), D*>);
static_assert(std::is_invocable_v<void(const void*), D*>);
CHECK(uarg{&d}.can_cast_to<void*>());
CHECK(uarg{&d}.can_cast_to<const void*>());
CHECK(uarg{&d}.cast<void*>() == &d);
CHECK(uarg{&d}.cast<const void*>() == &d);
}
SUBCASE("const D* -> void*") {
const D d;
static_assert(!std::is_invocable_v<void(void*), const D*>);
static_assert(std::is_invocable_v<void(const void*), const D*>);
CHECK_FALSE(uarg{&d}.can_cast_to<void*>());
CHECK(uarg{&d}.can_cast_to<const void*>());
CHECK_THROWS(std::ignore = uarg{&d}.cast<void*>());
CHECK(uarg{&d}.cast<const void*>() == &d);
}
SUBCASE("D[2] -> void*") {
D arr[2];
static_assert(std::is_invocable_v<void(void*), D (&) [2]>);
static_assert(std::is_invocable_v<void(const void*), D (&) [2]>);
CHECK(uarg{arr}.can_cast_to<void*>());
CHECK(uarg{arr}.can_cast_to<const void*>());
CHECK(uarg{arr}.cast<void*>() == &arr);
CHECK(uarg{arr}.cast<const void*>() == &arr);
}
SUBCASE("const D[2] -> void*") {
const D arr[2];
static_assert(!std::is_invocable_v<void(void*), const D (&) [2]>);
static_assert(std::is_invocable_v<void(const void*), const D (&) [2]>);
CHECK_FALSE(uarg{arr}.can_cast_to<void*>());
CHECK(uarg{arr}.can_cast_to<const void*>());
CHECK_THROWS(std::ignore = uarg{arr}.cast<void*>());
CHECK(uarg{arr}.cast<const void*>() == &arr);
}
}
TEST_CASE("meta/meta_utilities/arg7/cast/from_nullptr") {
namespace meta = meta_hpp;
using meta::detail::uarg;
SUBCASE("nullptr -> *") {
static_assert(std::is_invocable_v<void(int*), std::nullptr_t>);
static_assert(std::is_invocable_v<void(int*), std::nullptr_t&>);
static_assert(std::is_invocable_v<void(int*), std::nullptr_t&&>);
static_assert(std::is_invocable_v<void(int*), const std::nullptr_t>);
static_assert(std::is_invocable_v<void(int*), const std::nullptr_t&>);
static_assert(std::is_invocable_v<void(int*), const std::nullptr_t&&>);
static_assert(std::is_invocable_v<void(const D*), std::nullptr_t>);
static_assert(std::is_invocable_v<void(const D*), std::nullptr_t&>);
static_assert(std::is_invocable_v<void(const D*), std::nullptr_t&&>);
static_assert(std::is_invocable_v<void(const D*), const std::nullptr_t>);
static_assert(std::is_invocable_v<void(const D*), const std::nullptr_t&>);
static_assert(std::is_invocable_v<void(const D*), const std::nullptr_t&&>);
std::nullptr_t n1{nullptr};
const std::nullptr_t n2{nullptr};
CHECK(uarg{n1}.can_cast_to<int*>());
CHECK(uarg{std::move(n1)}.can_cast_to<int*>());
CHECK(uarg{n2}.can_cast_to<int*>());
CHECK(uarg{std::move(n2)}.can_cast_to<int*>());
CHECK(uarg{n1}.can_cast_to<const int*>());
CHECK(uarg{std::move(n1)}.can_cast_to<const int*>());
CHECK(uarg{n2}.can_cast_to<const int*>());
CHECK(uarg{std::move(n2)}.can_cast_to<const int*>());
CHECK(uarg{n1}.can_cast_to<D*>());
CHECK(uarg{std::move(n1)}.can_cast_to<D*>());
CHECK(uarg{n2}.can_cast_to<D*>());
CHECK(uarg{std::move(n2)}.can_cast_to<D*>());
CHECK(uarg{n1}.can_cast_to<const D*>());
CHECK(uarg{std::move(n1)}.can_cast_to<const D*>());
CHECK(uarg{n2}.can_cast_to<const D*>());
CHECK(uarg{std::move(n2)}.can_cast_to<const D*>());
//
CHECK(uarg{n1}.cast<int*>() == nullptr);
CHECK(uarg{std::move(n1)}.cast<int*>() == nullptr);
CHECK(uarg{n2}.cast<int*>() == nullptr);
CHECK(uarg{std::move(n2)}.cast<int*>() == nullptr);
CHECK(uarg{n1}.cast<const int*>() == nullptr);
CHECK(uarg{std::move(n1)}.cast<const int*>() == nullptr);
CHECK(uarg{n2}.cast<const int*>() == nullptr);
CHECK(uarg{std::move(n2)}.cast<const int*>() == nullptr);
CHECK(uarg{n1}.cast<D*>() == nullptr);
CHECK(uarg{std::move(n1)}.cast<D*>() == nullptr);
CHECK(uarg{n2}.cast<D*>() == nullptr);
CHECK(uarg{std::move(n2)}.cast<D*>() == nullptr);
CHECK(uarg{n1}.cast<const D*>() == nullptr);
CHECK(uarg{std::move(n1)}.cast<const D*>() == nullptr);
CHECK(uarg{n2}.cast<const D*>() == nullptr);
CHECK(uarg{std::move(n2)}.cast<const D*>() == nullptr);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/*******************************************************************************
* 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"
TEST_CASE("meta/meta_utilities/detail") {
namespace meta = meta_hpp;
SUBCASE("cvref_traits") {
static_assert(!meta::detail::cvref_traits<int>::is_lvalue);
static_assert(!meta::detail::cvref_traits<int>::is_rvalue);
static_assert(!meta::detail::cvref_traits<int>::is_const);
static_assert(!meta::detail::cvref_traits<int>::is_volatile);
static_assert(!meta::detail::cvref_traits<const int>::is_lvalue);
static_assert(!meta::detail::cvref_traits<const int>::is_rvalue);
static_assert(meta::detail::cvref_traits<const int>::is_const);
static_assert(!meta::detail::cvref_traits<const int>::is_volatile);
static_assert(!meta::detail::cvref_traits<const volatile int>::is_lvalue);
static_assert(!meta::detail::cvref_traits<const volatile int>::is_rvalue);
static_assert(meta::detail::cvref_traits<const volatile int>::is_const);
static_assert(meta::detail::cvref_traits<const volatile int>::is_volatile);
static_assert(meta::detail::cvref_traits<int&>::is_lvalue);
static_assert(!meta::detail::cvref_traits<int&>::is_rvalue);
static_assert(!meta::detail::cvref_traits<int&>::is_const);
static_assert(!meta::detail::cvref_traits<int&>::is_volatile);
static_assert(meta::detail::cvref_traits<const int&>::is_lvalue);
static_assert(!meta::detail::cvref_traits<const int&>::is_rvalue);
static_assert(meta::detail::cvref_traits<const int&>::is_const);
static_assert(!meta::detail::cvref_traits<const int&>::is_volatile);
static_assert(meta::detail::cvref_traits<const volatile int&>::is_lvalue);
static_assert(!meta::detail::cvref_traits<const volatile int&>::is_rvalue);
static_assert(meta::detail::cvref_traits<const volatile int&>::is_const);
static_assert(meta::detail::cvref_traits<const volatile int&>::is_volatile);
static_assert(!meta::detail::cvref_traits<int&&>::is_lvalue);
static_assert(meta::detail::cvref_traits<int&&>::is_rvalue);
static_assert(!meta::detail::cvref_traits<int&&>::is_const);
static_assert(!meta::detail::cvref_traits<int&&>::is_volatile);
static_assert(!meta::detail::cvref_traits<const int&&>::is_lvalue);
static_assert(meta::detail::cvref_traits<const int&&>::is_rvalue);
static_assert(meta::detail::cvref_traits<const int&&>::is_const);
static_assert(!meta::detail::cvref_traits<const int&&>::is_volatile);
static_assert(!meta::detail::cvref_traits<const volatile int&&>::is_lvalue);
static_assert(meta::detail::cvref_traits<const volatile int&&>::is_rvalue);
static_assert(meta::detail::cvref_traits<const volatile int&&>::is_const);
static_assert(meta::detail::cvref_traits<const volatile int&&>::is_volatile);
}
SUBCASE("cvref_traits::copy_to") {
static_assert(std::is_same_v<meta::detail::cvref_traits<float>::copy_to<int>, int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float>::copy_to<int>, const int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float>::copy_to<int>, const volatile int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<float&>::copy_to<int>, int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float&>::copy_to<int>, const int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<volatile float&>::copy_to<int>, volatile int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float&&>::copy_to<int>, const volatile int&&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<float>::copy_to<int&>, int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float>::copy_to<int&>, const int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float>::copy_to<int&>, const volatile int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<float&>::copy_to<int&>, int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float&>::copy_to<int&>, const int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<volatile float&>::copy_to<int&>, volatile int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float&&>::copy_to<int&>, const volatile int&&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<float>::copy_to<const volatile int&&>, int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float>::copy_to<const volatile int&&>, const int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float>::copy_to<const volatile int&&>, const volatile int>);
static_assert(std::is_same_v<meta::detail::cvref_traits<float&>::copy_to<const volatile int&&>, int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const float&>::copy_to<const volatile int&&>, const int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<volatile float&>::copy_to<const volatile int&&>, volatile int&>);
static_assert(std::is_same_v<meta::detail::cvref_traits<const volatile float&&>::copy_to<const volatile int&&>, const volatile int&&>);
}
}

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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
{
const double pi_v{3.1415926536};
enum class color : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
};
struct ivec2 {
int x{};
int y{};
[[maybe_unused]] explicit ivec2(int nv) : x{nv}, y{nv} {}
[[maybe_unused]] ivec2(int nx, int ny) : x{nx}, y{ny} {}
ivec2& add(const ivec2& other) noexcept {
x += other.x;
y += other.y;
return *this;
}
static ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
};
}
TEST_CASE("meta/meta_utilities/hash") {
namespace meta = meta_hpp;
meta::enum_<color>()
.evalue_("red", color::red)
.evalue_("green", color::green)
.evalue_("blue", color::blue);
meta::class_<ivec2>()
.constructor_<int>()
.constructor_<int, int>()
.destructor_()
.member_("x", &ivec2::x)
.member_("y", &ivec2::y)
.method_("add", &ivec2::add)
.function_("iadd", &ivec2::iadd);
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
const meta::constructor ivec2_ctor = ivec2_type.get_constructor_with<int>();
const meta::destructor ivec2_dtor = ivec2_type.get_destructors().begin()->second;
const meta::function ivec2_function = ivec2_type.get_function("iadd");
const meta::argument ivec2_function_arg = ivec2_function.get_argument(0);
const meta::member ivec2_member = ivec2_type.get_member("x");
const meta::method ivec2_method = ivec2_type.get_method("add");
const meta::enum_type color_type = meta::resolve_type<color>();
const meta::evalue red_color = color_type.get_evalue("red");
const meta::scope local_scope = meta::local_scope_("local-scope")
.variable_("pi_v", &pi_v);
const meta::variable pi_variable = local_scope.get_variable("pi_v");
SUBCASE("index_family") {
std::hash<meta::argument_index>{}(ivec2_function_arg.get_index());
std::hash<meta::constructor_index>{}(ivec2_ctor.get_index());
std::hash<meta::destructor_index>{}(ivec2_dtor.get_index());
std::hash<meta::evalue_index>{}(red_color.get_index());
std::hash<meta::function_index>{}(ivec2_function.get_index());
std::hash<meta::member_index>{}(ivec2_member.get_index());
std::hash<meta::method_index>{}(ivec2_method.get_index());
std::hash<meta::scope_index>{}(local_scope.get_index());
std::hash<meta::variable_index>{}(pi_variable.get_index());
}
SUBCASE("type_family") {
std::hash<meta::any_type>{}(meta::resolve_type<ivec2>());
std::hash<meta::array_type>{}(meta::resolve_type<int[]>());
std::hash<meta::class_type>{}(meta::resolve_type<ivec2>());
std::hash<meta::constructor_type>{}(ivec2_ctor.get_type());
std::hash<meta::destructor_type>{}(ivec2_dtor.get_type());
std::hash<meta::enum_type>{}(red_color.get_type());
std::hash<meta::function_type>{}(ivec2_function.get_type());
std::hash<meta::member_type>{}(ivec2_member.get_type());
std::hash<meta::method_type>{}(ivec2_method.get_type());
std::hash<meta::nullptr_type>{}(meta::resolve_type<std::nullptr_t>());
std::hash<meta::number_type>{}(meta::resolve_type<int>());
std::hash<meta::pointer_type>{}(meta::resolve_type<int*>());
std::hash<meta::reference_type>{}(meta::resolve_type<int&>());
std::hash<meta::void_type>{}(meta::resolve_type<void>());
}
}

View File

@@ -0,0 +1,384 @@
/*******************************************************************************
* 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 fake {
int i = 10;
};
struct clazz {
int ii = 1;
[[nodiscard]] int m1() { return ii; }
[[nodiscard]] int m2() & { return ii; }
[[nodiscard]] int m3() && { return ii; }
[[nodiscard]] int m4() const { return ii; }
[[nodiscard]] int m5() const & { return ii; }
[[nodiscard]] int m6() const && { return ii; }
};
struct dclazz : fake, clazz {};
}
// NOLINTNEXTLINE(*-macro-usage)
#define META_HPP_CHECK_INVOCABLE(Inst, FName, Qualifiers)\
{\
using namespace meta::detail;\
auto method_ptr = meta::select_overload<int() Qualifiers>(&clazz::FName);\
meta::method m_state{method_state::make<meta::method_policy::as_copy_t>("", method_ptr, {})};\
\
if ( std::is_invocable_v<decltype(method_ptr), decltype(Inst)> ) {\
CHECK(uinst{Inst}.can_cast_to<clazz Qualifiers>());\
CHECK(uinst_base{type_list<decltype(Inst)>{}}.can_cast_to<clazz Qualifiers>());\
CHECK_NOTHROW(std::ignore = uinst{Inst}.cast<clazz Qualifiers>());\
\
CHECK(m_state.is_invocable_with<decltype(Inst)>());\
CHECK(m_state.invoke(Inst) == 1);\
} else {\
CHECK_FALSE(uinst{Inst}.can_cast_to<clazz Qualifiers>());\
CHECK_FALSE(uinst_base{type_list<decltype(Inst)>{}}.can_cast_to<clazz Qualifiers>());\
CHECK_THROWS(std::ignore = uinst{Inst}.cast<clazz Qualifiers>());\
\
CHECK_FALSE(m_state.is_invocable_with<decltype(Inst)>());\
CHECK_THROWS(m_state.invoke(Inst));\
}\
}
// NOLINTNEXTLINE(*-macro-usage)
#define META_HPP_CHECK_INVOCABLE_2(FromValue, FName, FromType, ToQualifiers)\
{\
using namespace meta::detail;\
auto method_ptr = meta::select_overload<int() ToQualifiers>(&clazz::FName);\
meta::method m_state{method_state::make<meta::method_policy::as_copy_t>("", method_ptr, {})};\
\
if ( std::is_invocable_v<decltype(method_ptr), FromType> ) {\
CHECK(m_state.is_invocable_with<FromType>());\
CHECK(m_state.is_invocable_with(FromValue));\
CHECK(m_state.invoke(FromValue) == 1);\
} else {\
CHECK_FALSE(m_state.is_invocable_with<FromType>());\
CHECK_FALSE(m_state.is_invocable_with(FromValue));\
CHECK_THROWS(m_state.invoke(FromValue));\
}\
}
TEST_CASE("meta/meta_utilities/inst2") {
namespace meta = meta_hpp;
meta::class_<fake>();
meta::class_<clazz>();
meta::class_<dclazz>().base_<fake>().base_<clazz>();
}
TEST_CASE("meta/meta_utilities/inst2/refs") {
namespace meta = meta_hpp;
{
// lvalue
auto LV = []() -> clazz& { static clazz v; return v; };
auto LV2 = []() -> dclazz& { static dclazz v; return v; };
{
meta::detail::uinst i{LV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::lvalue);
}
META_HPP_CHECK_INVOCABLE(LV(), m1, )
META_HPP_CHECK_INVOCABLE(LV(), m2, &)
META_HPP_CHECK_INVOCABLE(LV(), m3, &&)
META_HPP_CHECK_INVOCABLE(LV(), m4, const)
META_HPP_CHECK_INVOCABLE(LV(), m5, const &)
META_HPP_CHECK_INVOCABLE(LV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(LV2(), m1, )
META_HPP_CHECK_INVOCABLE(LV2(), m2, &)
META_HPP_CHECK_INVOCABLE(LV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(LV2(), m4, const)
META_HPP_CHECK_INVOCABLE(LV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(LV2(), m6, const &&)
}
{
// const lvalue
auto CLV = []() -> const clazz& { static clazz v; return v; };
auto CLV2 = []() -> const dclazz& { static dclazz v; return v; };
{
meta::detail::uinst i{CLV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::const_lvalue);
}
META_HPP_CHECK_INVOCABLE(CLV(), m1, )
META_HPP_CHECK_INVOCABLE(CLV(), m2, &)
META_HPP_CHECK_INVOCABLE(CLV(), m3, &&)
META_HPP_CHECK_INVOCABLE(CLV(), m4, const)
META_HPP_CHECK_INVOCABLE(CLV(), m5, const &)
META_HPP_CHECK_INVOCABLE(CLV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(CLV2(), m1, )
META_HPP_CHECK_INVOCABLE(CLV2(), m2, &)
META_HPP_CHECK_INVOCABLE(CLV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(CLV2(), m4, const)
META_HPP_CHECK_INVOCABLE(CLV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(CLV2(), m6, const &&)
}
{
// xvalue
auto XV = []() -> clazz&& { static clazz v; return std::move(v); };
auto XV2 = []() -> dclazz&& { static dclazz v; return std::move(v); };
{
meta::detail::uinst i{XV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::rvalue);
}
META_HPP_CHECK_INVOCABLE(XV(), m1, )
META_HPP_CHECK_INVOCABLE(XV(), m2, &)
META_HPP_CHECK_INVOCABLE(XV(), m3, &&)
META_HPP_CHECK_INVOCABLE(XV(), m4, const)
META_HPP_CHECK_INVOCABLE(XV(), m5, const &)
META_HPP_CHECK_INVOCABLE(XV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(XV2(), m1, )
META_HPP_CHECK_INVOCABLE(XV2(), m2, &)
META_HPP_CHECK_INVOCABLE(XV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(XV2(), m4, const)
META_HPP_CHECK_INVOCABLE(XV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(XV2(), m6, const &&)
}
{
// const xvalue
auto CXV = []() -> const clazz&& { static clazz v; return std::move(v); };
auto CXV2 = []() -> const dclazz&& { static dclazz v; return std::move(v); };
{
meta::detail::uinst i{CXV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::const_rvalue);
}
META_HPP_CHECK_INVOCABLE(CXV(), m1, )
META_HPP_CHECK_INVOCABLE(CXV(), m2, &)
META_HPP_CHECK_INVOCABLE(CXV(), m3, &&)
META_HPP_CHECK_INVOCABLE(CXV(), m4, const)
META_HPP_CHECK_INVOCABLE(CXV(), m5, const &)
META_HPP_CHECK_INVOCABLE(CXV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(CXV2(), m1, )
META_HPP_CHECK_INVOCABLE(CXV2(), m2, &)
META_HPP_CHECK_INVOCABLE(CXV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(CXV2(), m4, const)
META_HPP_CHECK_INVOCABLE(CXV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(CXV2(), m6, const &&)
}
{
// prvalue
auto PRV = []() -> clazz { return clazz{}; };
auto PRV2 = []() -> dclazz { return dclazz{}; };
{
meta::detail::uinst i{PRV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::rvalue);
}
META_HPP_CHECK_INVOCABLE(PRV(), m1, )
META_HPP_CHECK_INVOCABLE(PRV(), m2, &)
META_HPP_CHECK_INVOCABLE(PRV(), m3, &&)
META_HPP_CHECK_INVOCABLE(PRV(), m4, const)
META_HPP_CHECK_INVOCABLE(PRV(), m5, const &)
META_HPP_CHECK_INVOCABLE(PRV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(PRV2(), m1, )
META_HPP_CHECK_INVOCABLE(PRV2(), m2, &)
META_HPP_CHECK_INVOCABLE(PRV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(PRV2(), m4, const)
META_HPP_CHECK_INVOCABLE(PRV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(PRV2(), m6, const &&)
}
{
// const prvalue
auto CPRV = []() -> const clazz { return clazz{}; };
auto CPRV2 = []() -> const dclazz { return dclazz{}; };
{
meta::detail::uinst i{CPRV()};
CHECK(i.get_raw_type() == meta::resolve_type<clazz>());
CHECK(i.get_ref_type() == meta::detail::uinst::ref_types::const_rvalue);
}
META_HPP_CHECK_INVOCABLE(CPRV(), m1, )
META_HPP_CHECK_INVOCABLE(CPRV(), m2, &)
META_HPP_CHECK_INVOCABLE(CPRV(), m3, &&)
META_HPP_CHECK_INVOCABLE(CPRV(), m4, const)
META_HPP_CHECK_INVOCABLE(CPRV(), m5, const &)
META_HPP_CHECK_INVOCABLE(CPRV(), m6, const &&)
META_HPP_CHECK_INVOCABLE(CPRV2(), m1, )
META_HPP_CHECK_INVOCABLE(CPRV2(), m2, &)
META_HPP_CHECK_INVOCABLE(CPRV2(), m3, &&)
META_HPP_CHECK_INVOCABLE(CPRV2(), m4, const)
META_HPP_CHECK_INVOCABLE(CPRV2(), m5, const &)
META_HPP_CHECK_INVOCABLE(CPRV2(), m6, const &&)
}
}
TEST_CASE("meta/meta_utilities/inst2/values") {
namespace meta = meta_hpp;
{
// lvalue
auto LV = []() -> meta::uvalue& { static meta::uvalue v{clazz{}}; return v; };
auto LV2 = []() -> meta::uvalue& { static meta::uvalue v{dclazz{}}; return v; };
meta::detail::uarg a{LV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::lvalue);
META_HPP_CHECK_INVOCABLE_2(LV(), m1, clazz&, )
META_HPP_CHECK_INVOCABLE_2(LV(), m2, clazz&, &)
META_HPP_CHECK_INVOCABLE_2(LV(), m3, clazz&, &&)
META_HPP_CHECK_INVOCABLE_2(LV(), m4, clazz&, const)
META_HPP_CHECK_INVOCABLE_2(LV(), m5, clazz&, const &)
META_HPP_CHECK_INVOCABLE_2(LV(), m6, clazz&, const &&)
META_HPP_CHECK_INVOCABLE_2(LV2(), m1, dclazz&, )
META_HPP_CHECK_INVOCABLE_2(LV2(), m2, dclazz&, &)
META_HPP_CHECK_INVOCABLE_2(LV2(), m3, dclazz&, &&)
META_HPP_CHECK_INVOCABLE_2(LV2(), m4, dclazz&, const)
META_HPP_CHECK_INVOCABLE_2(LV2(), m5, dclazz&, const &)
META_HPP_CHECK_INVOCABLE_2(LV2(), m6, dclazz&, const &&)
}
{
// const lvalue
auto CLV = []() -> const meta::uvalue& { static meta::uvalue v{clazz{}}; return v; };
auto CLV2 = []() -> const meta::uvalue& { static meta::uvalue v{dclazz{}}; return v; };
meta::detail::uarg a{CLV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::const_lvalue);
META_HPP_CHECK_INVOCABLE_2(CLV(), m1, const clazz&, )
META_HPP_CHECK_INVOCABLE_2(CLV(), m2, const clazz&, &)
META_HPP_CHECK_INVOCABLE_2(CLV(), m3, const clazz&, &&)
META_HPP_CHECK_INVOCABLE_2(CLV(), m4, const clazz&, const)
META_HPP_CHECK_INVOCABLE_2(CLV(), m5, const clazz&, const &)
META_HPP_CHECK_INVOCABLE_2(CLV(), m6, const clazz&, const &&)
META_HPP_CHECK_INVOCABLE_2(CLV2(), m1, const dclazz&, )
META_HPP_CHECK_INVOCABLE_2(CLV2(), m2, const dclazz&, &)
META_HPP_CHECK_INVOCABLE_2(CLV2(), m3, const dclazz&, &&)
META_HPP_CHECK_INVOCABLE_2(CLV2(), m4, const dclazz&, const)
META_HPP_CHECK_INVOCABLE_2(CLV2(), m5, const dclazz&, const &)
META_HPP_CHECK_INVOCABLE_2(CLV2(), m6, const dclazz&, const &&)
}
{
// xvalue
auto XV = []() -> meta::uvalue&& { static meta::uvalue v{clazz{}}; return std::move(v); };
auto XV2 = []() -> meta::uvalue&& { static meta::uvalue v{dclazz{}}; return std::move(v); };
meta::detail::uarg a{XV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::rvalue);
META_HPP_CHECK_INVOCABLE_2(XV(), m1, clazz&&, )
META_HPP_CHECK_INVOCABLE_2(XV(), m2, clazz&&, &)
META_HPP_CHECK_INVOCABLE_2(XV(), m3, clazz&&, &&)
META_HPP_CHECK_INVOCABLE_2(XV(), m4, clazz&&, const)
META_HPP_CHECK_INVOCABLE_2(XV(), m5, clazz&&, const &)
META_HPP_CHECK_INVOCABLE_2(XV(), m6, clazz&&, const &&)
META_HPP_CHECK_INVOCABLE_2(XV2(), m1, dclazz&&, )
META_HPP_CHECK_INVOCABLE_2(XV2(), m2, dclazz&&, &)
META_HPP_CHECK_INVOCABLE_2(XV2(), m3, dclazz&&, &&)
META_HPP_CHECK_INVOCABLE_2(XV2(), m4, dclazz&&, const)
META_HPP_CHECK_INVOCABLE_2(XV2(), m5, dclazz&&, const &)
META_HPP_CHECK_INVOCABLE_2(XV2(), m6, dclazz&&, const &&)
}
{
// const xvalue
auto CXV = []() -> const meta::uvalue&& { static meta::uvalue v{clazz{}}; return std::move(v); };
auto CXV2 = []() -> const meta::uvalue&& { static meta::uvalue v{dclazz{}}; return std::move(v); };
meta::detail::uarg a{CXV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::const_rvalue);
META_HPP_CHECK_INVOCABLE_2(CXV(), m1, const clazz&&, )
META_HPP_CHECK_INVOCABLE_2(CXV(), m2, const clazz&&, &)
META_HPP_CHECK_INVOCABLE_2(CXV(), m3, const clazz&&, &&)
META_HPP_CHECK_INVOCABLE_2(CXV(), m4, const clazz&&, const)
META_HPP_CHECK_INVOCABLE_2(CXV(), m5, const clazz&&, const &)
META_HPP_CHECK_INVOCABLE_2(CXV(), m6, const clazz&&, const &&)
META_HPP_CHECK_INVOCABLE_2(CXV2(), m1, const dclazz&&, )
META_HPP_CHECK_INVOCABLE_2(CXV2(), m2, const dclazz&&, &)
META_HPP_CHECK_INVOCABLE_2(CXV2(), m3, const dclazz&&, &&)
META_HPP_CHECK_INVOCABLE_2(CXV2(), m4, const dclazz&&, const)
META_HPP_CHECK_INVOCABLE_2(CXV2(), m5, const dclazz&&, const &)
META_HPP_CHECK_INVOCABLE_2(CXV2(), m6, const dclazz&&, const &&)
}
{
// prvalue
auto PRV = []() -> meta::uvalue { return meta::uvalue{clazz{}}; };
auto PRV2 = []() -> meta::uvalue { return meta::uvalue{dclazz{}}; };
meta::detail::uarg a{PRV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::rvalue);
META_HPP_CHECK_INVOCABLE_2(PRV(), m1, clazz, )
META_HPP_CHECK_INVOCABLE_2(PRV(), m2, clazz, &)
META_HPP_CHECK_INVOCABLE_2(PRV(), m3, clazz, &&)
META_HPP_CHECK_INVOCABLE_2(PRV(), m4, clazz, const)
META_HPP_CHECK_INVOCABLE_2(PRV(), m5, clazz, const &)
META_HPP_CHECK_INVOCABLE_2(PRV(), m6, clazz, const &&)
META_HPP_CHECK_INVOCABLE_2(PRV2(), m1, dclazz, )
META_HPP_CHECK_INVOCABLE_2(PRV2(), m2, dclazz, &)
META_HPP_CHECK_INVOCABLE_2(PRV2(), m3, dclazz, &&)
META_HPP_CHECK_INVOCABLE_2(PRV2(), m4, dclazz, const)
META_HPP_CHECK_INVOCABLE_2(PRV2(), m5, dclazz, const &)
META_HPP_CHECK_INVOCABLE_2(PRV2(), m6, dclazz, const &&)
}
{
// const prvalue
auto CPRV = []() -> const meta::uvalue { return meta::uvalue{clazz{}}; };
auto CPRV2 = []() -> const meta::uvalue { return meta::uvalue{dclazz{}}; };
meta::detail::uarg a{CPRV()};
CHECK(a.get_raw_type() == meta::resolve_type<clazz>());
CHECK(a.get_ref_type() == meta::detail::uarg::ref_types::const_rvalue);
META_HPP_CHECK_INVOCABLE_2(CPRV(), m1, const clazz, )
META_HPP_CHECK_INVOCABLE_2(CPRV(), m2, const clazz, &)
META_HPP_CHECK_INVOCABLE_2(CPRV(), m3, const clazz, &&)
META_HPP_CHECK_INVOCABLE_2(CPRV(), m4, const clazz, const)
META_HPP_CHECK_INVOCABLE_2(CPRV(), m5, const clazz, const &)
META_HPP_CHECK_INVOCABLE_2(CPRV(), m6, const clazz, const &&)
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m1, const dclazz, )
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m2, const dclazz, &)
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m3, const dclazz, &&)
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m4, const dclazz, const)
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m5, const dclazz, const &)
META_HPP_CHECK_INVOCABLE_2(CPRV2(), m6, const dclazz, const &&)
}
}

View File

@@ -0,0 +1,85 @@
/*******************************************************************************
* 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 clazz {
int member{1};
int method(int i) const { return i; }
static int function(int i) { return i; }
};
}
TEST_CASE("meta/meta_utilities/invoke") {
namespace meta = meta_hpp;
meta::class_<clazz>()
.member_("member", &clazz::member)
.method_("method", &clazz::method)
.function_("function", &clazz::function);
const meta::class_type& clazz_type = meta::resolve_type<clazz>();
REQUIRE(clazz_type);
const meta::member& clazz_member = clazz_type.get_member("member");
const meta::method& clazz_method = clazz_type.get_method("method");
const meta::function& clazz_function = clazz_type.get_function("function");
REQUIRE((clazz_member && clazz_method && clazz_function));
{
CHECK(meta::invoke(&clazz::function, 3) == 3);
CHECK(meta::invoke(&clazz::function, meta::uvalue(3)) == 3);
CHECK(meta::invoke(clazz_function, 3) == 3);
CHECK(meta::invoke(clazz_function, meta::uvalue(3)) == 3);
CHECK(meta::is_invocable_with(clazz_function, 3));
CHECK(meta::is_invocable_with(clazz_function, meta::uvalue(3)));
CHECK(meta::is_invocable_with<int>(clazz_function));
using function_t = decltype(&clazz::function);
CHECK(meta::is_invocable_with<function_t>(3));
CHECK(meta::is_invocable_with<function_t>(meta::uvalue(3)));
CHECK(meta::is_invocable_with<function_t, int>());
}
{
clazz cl;
CHECK(meta::invoke(&clazz::member, cl) == 1);
CHECK(meta::invoke(&clazz::member, meta::uvalue{cl}) == 1);
CHECK(meta::invoke(clazz_member, cl) == 1);
CHECK(meta::invoke(clazz_member, meta::uvalue{cl}) == 1);
CHECK(meta::is_invocable_with(clazz_member, cl));
CHECK(meta::is_invocable_with(clazz_member, meta::uvalue{cl}));
CHECK(meta::is_invocable_with<const clazz&>(clazz_member));
using member_t = decltype(&clazz::member);
CHECK(meta::is_invocable_with<member_t>(cl));
CHECK(meta::is_invocable_with<member_t>(meta::uvalue{cl}));
CHECK(meta::is_invocable_with<member_t, const clazz&>());
}
{
clazz cl;
CHECK(meta::invoke(&clazz::method, cl, 2) == 2);
CHECK(meta::invoke(&clazz::method, meta::uvalue{cl}, meta::uvalue(2)) == 2);
CHECK(meta::invoke(clazz_method, cl, 2) == 2);
CHECK(meta::invoke(clazz_method, meta::uvalue{cl}, meta::uvalue(2)) == 2);
CHECK(meta::is_invocable_with(clazz_method, cl, 2));
CHECK(meta::is_invocable_with(clazz_method, meta::uvalue{cl}, meta::uvalue(2)));
CHECK(meta::is_invocable_with<const clazz&, int>(clazz_method));
using method_t = decltype(&clazz::method);
CHECK(meta::is_invocable_with<method_t>(cl, 2));
CHECK(meta::is_invocable_with<method_t>(meta::uvalue{cl}, meta::uvalue(2)));
CHECK(meta::is_invocable_with<method_t, const clazz&, int>());
}
}

View File

@@ -0,0 +1,413 @@
/*******************************************************************************
* 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 ivec2 final {
int x{};
int y{};
ivec2() = delete;
[[maybe_unused]] explicit ivec2(int nv): x{nv}, y{nv} {}
[[maybe_unused]] ivec2(int nx, int ny): x{nx}, y{ny} {}
[[maybe_unused]] ivec2(ivec2&& other) noexcept
: x{other.x}
, y{other.y} {
other.x = 0;
other.y = 0;
++move_constructor_counter;
}
[[maybe_unused]] ivec2(const ivec2& other) noexcept
: x{other.x}
, y{other.y} {
++copy_constructor_counter;
}
~ivec2() noexcept {
++destructor_counter;
}
ivec2& operator=(ivec2&& other) = delete;
ivec2& operator=(const ivec2& other) = delete;
static int destructor_counter;
static int move_constructor_counter;
static int copy_constructor_counter;
};
struct ivec2_big final {
int x{};
int y{};
int dummy[42]{};
ivec2_big() = delete;
[[maybe_unused]] explicit ivec2_big(int nv): x{nv}, y{nv} {}
[[maybe_unused]] ivec2_big(int nx, int ny): x{nx}, y{ny} {}
[[maybe_unused]] ivec2_big(ivec2_big&& other) noexcept
: x{other.x}
, y{other.y} {
other.x = 0;
other.y = 0;
++move_constructor_counter;
}
[[maybe_unused]] ivec2_big(const ivec2_big& other) noexcept
: x{other.x}
, y{other.y} {
++copy_constructor_counter;
}
~ivec2_big() noexcept {
++destructor_counter;
}
ivec2_big& operator=(ivec2_big&& other) = delete;
ivec2_big& operator=(const ivec2_big& other) = delete;
static int destructor_counter;
static int move_constructor_counter;
static int copy_constructor_counter;
};
[[maybe_unused]] bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
[[maybe_unused]] bool operator==(const ivec2_big& l, const ivec2_big& r) noexcept {
return l.x == r.x && l.y == r.y;
}
int ivec2::destructor_counter{0};
int ivec2::move_constructor_counter{0};
int ivec2::copy_constructor_counter{0};
int ivec2_big::destructor_counter{0};
int ivec2_big::move_constructor_counter{0};
int ivec2_big::copy_constructor_counter{0};
}
TEST_CASE("meta/meta_utilities/value2") {
namespace meta = meta_hpp;
meta::class_<ivec2>()
.constructor_<int>()
.constructor_<int, int>()
.constructor_<ivec2&&>()
.constructor_<const ivec2&>()
.member_("x", &ivec2::x)
.member_("y", &ivec2::y);
meta::class_<ivec2_big>()
.constructor_<int>()
.constructor_<int, int>()
.constructor_<ivec2_big&&>()
.constructor_<const ivec2_big&>()
.member_("x", &ivec2_big::x)
.member_("y", &ivec2_big::y);
}
TEST_CASE("meta/meta_utilities/value2/counters/small") {
namespace meta = meta_hpp;
ivec2::destructor_counter = 0;
ivec2::move_constructor_counter = 0;
ivec2::copy_constructor_counter = 0;
SUBCASE("def ctor") {
{
meta::uvalue v{};
CHECK(ivec2::destructor_counter == 0);
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 0);
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("val ctor") {
{
meta::uvalue v{ivec2{1,2}};
CHECK(ivec2::destructor_counter == 1);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 2);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("move ctor") {
{
meta::uvalue v1{ivec2{1,2}};
meta::uvalue v2{std::move(v1)};
CHECK_FALSE(v1);
CHECK(v2.get_as<ivec2>().x == 1);
CHECK(ivec2::destructor_counter == 2);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 3);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("copy ctor") {
{
meta::uvalue v1{ivec2{1,2}};
meta::uvalue v2{std::as_const(v1)};
CHECK(v1.get_as<ivec2>().x == 1);
CHECK(v2.get_as<ivec2>().y == 2);
CHECK(ivec2::destructor_counter == 1);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 1);
}
CHECK(ivec2::destructor_counter == 3);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 1);
}
SUBCASE("swap") {
{
meta::uvalue v1{ivec2{1,2}};
meta::uvalue v2{ivec2{3,4}};
CHECK(ivec2::destructor_counter == 2);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2>().x == 3);
CHECK(v2.get_as<ivec2>().x == 1);
CHECK(ivec2::destructor_counter == 5);
CHECK(ivec2::move_constructor_counter == 5);
CHECK(ivec2::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 7);
CHECK(ivec2::move_constructor_counter == 5);
CHECK(ivec2::copy_constructor_counter == 0);
}
}
TEST_CASE("meta/meta_utilities/value2/counters/big") {
namespace meta = meta_hpp;
ivec2_big::destructor_counter = 0;
ivec2_big::move_constructor_counter = 0;
ivec2_big::copy_constructor_counter = 0;
SUBCASE("def ctor") {
{
meta::uvalue v{};
CHECK(ivec2_big::destructor_counter == 0);
CHECK(ivec2_big::move_constructor_counter == 0);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2_big::destructor_counter == 0);
CHECK(ivec2_big::move_constructor_counter == 0);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
SUBCASE("val ctor") {
{
meta::uvalue v{ivec2_big{1,2}};
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
SUBCASE("move ctor") {
{
meta::uvalue v1{ivec2_big{1,2}};
meta::uvalue v2{std::move(v1)};
CHECK_FALSE(v1);
CHECK(v2.get_as<ivec2_big>().x == 1);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
SUBCASE("copy ctor") {
{
meta::uvalue v1{ivec2_big{1,2}};
meta::uvalue v2{std::as_const(v1)};
CHECK(v1.get_as<ivec2_big>().x == 1);
CHECK(v2.get_as<ivec2_big>().y == 2);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 1);
}
CHECK(ivec2_big::destructor_counter == 3);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 1);
}
SUBCASE("swap") {
{
meta::uvalue v1{ivec2_big{1,2}};
meta::uvalue v2{ivec2_big{3,4}};
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 2);
CHECK(ivec2_big::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2_big>().x == 3);
CHECK(v2.get_as<ivec2_big>().x == 1);
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 2);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2_big::destructor_counter == 4);
CHECK(ivec2_big::move_constructor_counter == 2);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
}
TEST_CASE("meta/meta_utilities/value2/counters/swap") {
namespace meta = meta_hpp;
ivec2::destructor_counter = 0;
ivec2::move_constructor_counter = 0;
ivec2::copy_constructor_counter = 0;
ivec2_big::destructor_counter = 0;
ivec2_big::move_constructor_counter = 0;
ivec2_big::copy_constructor_counter = 0;
SUBCASE("empty/small") {
{
meta::uvalue v1{};
meta::uvalue v2{ivec2{1,2}};
CHECK(ivec2::destructor_counter == 1);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2>().x == 1);
CHECK_FALSE(v2);
CHECK(ivec2::destructor_counter == 2);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
v1.swap(v2);
CHECK_FALSE(v1);
CHECK(v2.get_as<ivec2>().y == 2);
CHECK(ivec2::destructor_counter == 3);
CHECK(ivec2::move_constructor_counter == 3);
CHECK(ivec2::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 4);
CHECK(ivec2::move_constructor_counter == 3);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("empty/big") {
{
meta::uvalue v1{};
meta::uvalue v2{ivec2_big{3,4}};
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2_big>().x == 3);
CHECK_FALSE(v2);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
v1.swap(v2);
CHECK_FALSE(v1);
CHECK(v2.get_as<ivec2_big>().y == 4);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
SUBCASE("small/big") {
{
meta::uvalue v1{ivec2{1,2}};
meta::uvalue v2{ivec2_big{3,4}};
CHECK(ivec2::destructor_counter == 1);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2_big>().x == 3);
CHECK(v2.get_as<ivec2>().x == 1);
CHECK(ivec2::destructor_counter == 2);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
v1.swap(v2);
CHECK(v1.get_as<ivec2>().y == 2);
CHECK(v2.get_as<ivec2_big>().y == 4);
CHECK(ivec2::destructor_counter == 3);
CHECK(ivec2::move_constructor_counter == 3);
CHECK(ivec2::copy_constructor_counter == 0);
CHECK(ivec2_big::destructor_counter == 1);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
CHECK(ivec2::destructor_counter == 4);
CHECK(ivec2::move_constructor_counter == 3);
CHECK(ivec2::copy_constructor_counter == 0);
CHECK(ivec2_big::destructor_counter == 2);
CHECK(ivec2_big::move_constructor_counter == 1);
CHECK(ivec2_big::copy_constructor_counter == 0);
}
}

View File

@@ -0,0 +1,326 @@
/*******************************************************************************
* 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 base0 {
int i{21};
};
struct base1 : virtual base0 {
int j{42};
};
struct base2 : virtual base0 {
int k{84};
};
struct derived : base1, base2 {
int l{168};
};
struct derived2 : base1, base2 {
int m{336};
};
}
TEST_CASE("meta/meta_utilities/value4") {
namespace meta = meta_hpp;
meta::class_<base0>();
meta::class_<base1>()
.base_<base0>();
meta::class_<base2>()
.base_<base0>();
meta::class_<derived>()
.base_<base1>()
.base_<base2>();
meta::class_<derived2>()
.base_<base1>()
.base_<base2>();
}
TEST_CASE("meta/meta_utilities/value4/get_type") {
namespace meta = meta_hpp;
SUBCASE("from ref") {
{
derived d{};
CHECK(meta::uvalue{d}.get_type() == meta::resolve_type<derived>());
}
{
const derived d{};
CHECK(meta::uvalue{d}.get_type() == meta::resolve_type<derived>());
}
}
SUBCASE("from ptr") {
{
derived d{};
derived* pd = &d;
CHECK(meta::uvalue{pd}.get_type() == meta::resolve_type<derived*>());
}
{
derived d{};
derived* const pd = &d;
CHECK(meta::uvalue{pd}.get_type() == meta::resolve_type<derived*>());
}
{
derived d{};
const derived* pd = &d;
CHECK(meta::uvalue{pd}.get_type() == meta::resolve_type<const derived*>());
}
{
derived d{};
const derived* const pd = &d;
CHECK(meta::uvalue{pd}.get_type() == meta::resolve_type<const derived*>());
}
}
}
TEST_CASE("meta/meta_utilities/value4/get_as") {
namespace meta = meta_hpp;
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived>()), derived&>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<derived>()), derived&>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<derived>()), const derived&>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<derived>()), const derived&>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().get_as<const derived*>()), const derived*>);
SUBCASE("derived to derived") {
{
meta::uvalue v{derived{}};
CHECK(v.get_as<derived>().l == 168);
CHECK_THROWS(std::ignore = v.get_as<derived2>());
}
{
const meta::uvalue v{derived{}};
CHECK(v.get_as<derived>().l == 168);
CHECK_THROWS(std::ignore = v.get_as<derived2>());
}
}
SUBCASE("derived to base") {
{
meta::uvalue v{derived{}};
CHECK(v.get_as<base2>().k == 84);
}
{
const meta::uvalue v{derived{}};
CHECK(v.get_as<base2>().k == 84);
}
}
SUBCASE("voidptr") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.get_as<void*>() == &d);
CHECK(v.get_as<const void*>() == &d);
}
{
const derived d{};
meta::uvalue v{&d};
CHECK_THROWS(std::ignore = v.get_as<void*>());
CHECK(v.get_as<const void*>() == &d);
}
{
meta::uvalue v{derived{}};
CHECK_THROWS(std::ignore = v.get_as<void*>());
CHECK_THROWS(std::ignore = v.get_as<const void*>());
}
}
SUBCASE("nullptr") {
{
meta::uvalue v{nullptr};
CHECK(v.get_as<void*>() == nullptr);
CHECK(v.get_as<const void*>() == nullptr);
CHECK(v.get_as<derived*>() == nullptr);
CHECK(v.get_as<const derived*>() == nullptr);
CHECK_THROWS(std::ignore = v.get_as<derived>());
}
{
const meta::uvalue v{nullptr};
CHECK(v.get_as<void*>() == nullptr);
CHECK(v.get_as<const void*>() == nullptr);
CHECK(v.get_as<derived*>() == nullptr);
CHECK(v.get_as<const derived*>() == nullptr);
CHECK_THROWS(std::ignore = v.get_as<derived>());
}
}
SUBCASE("derived* to derived*") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.get_as<derived*>()->l == 168);
CHECK(v.get_as<const derived*>()->l == 168);
CHECK_THROWS(std::ignore = v.get_as<derived2*>());
CHECK_THROWS(std::ignore = v.get_as<const derived2*>());
}
{
const derived d{};
meta::uvalue v{&d};
CHECK(v.get_as<const derived*>()->l == 168);
CHECK_THROWS(std::ignore = v.get_as<const derived2*>());
}
}
SUBCASE("derived* to base*") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.get_as<base2*>()->k == 84);
CHECK(v.get_as<const base2*>()->k == 84);
}
{
const derived d{};
meta::uvalue v{&d};
CHECK_THROWS(std::ignore = v.get_as<base2*>());
CHECK(v.get_as<const base2*>()->k == 84);
}
}
}
TEST_CASE("meta/meta_utilities/value4/try_get_as") {
namespace meta = meta_hpp;
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().try_get_as<derived>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().try_get_as<derived>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().try_get_as<derived>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().try_get_as<derived>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().try_get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().try_get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().try_get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().try_get_as<derived*>()), derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&>().try_get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<meta::uvalue&&>().try_get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&>().try_get_as<const derived*>()), const derived*>);
static_assert(std::is_same_v<decltype(std::declval<const meta::uvalue&&>().try_get_as<const derived*>()), const derived*>);
SUBCASE("derived to derived") {
{
meta::uvalue v{derived{}};
CHECK(v.try_get_as<derived>()->l == 168);
CHECK_FALSE(v.try_get_as<derived2>());
}
{
const meta::uvalue v{derived{}};
CHECK(v.try_get_as<derived>()->l == 168);
CHECK_FALSE(v.try_get_as<derived2>());
}
}
SUBCASE("derived to base") {
{
meta::uvalue v{derived{}};
CHECK(v.try_get_as<base2>()->k == 84);
}
{
const meta::uvalue v{derived{}};
CHECK(v.try_get_as<base2>()->k == 84);
}
}
SUBCASE("voidptr") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.try_get_as<void*>() == &d);
CHECK(v.try_get_as<const void*>() == &d);
}
{
const derived d{};
meta::uvalue v{&d};
CHECK_FALSE(v.try_get_as<void*>());
CHECK(v.try_get_as<const void*>() == &d);
}
{
meta::uvalue v{derived{}};
CHECK_FALSE(v.try_get_as<void*>());
CHECK_FALSE(v.try_get_as<const void*>());
}
}
SUBCASE("nullptr") {
{
meta::uvalue v{nullptr};
CHECK(v.try_get_as<void*>() == nullptr);
CHECK(v.try_get_as<const void*>() == nullptr);
CHECK(v.try_get_as<derived*>() == nullptr);
CHECK(v.try_get_as<const derived*>() == nullptr);
CHECK_FALSE(v.try_get_as<derived>());
}
{
const meta::uvalue v{nullptr};
CHECK(v.try_get_as<void*>() == nullptr);
CHECK(v.try_get_as<const void*>() == nullptr);
CHECK(v.try_get_as<derived*>() == nullptr);
CHECK(v.try_get_as<const derived*>() == nullptr);
CHECK_FALSE(v.try_get_as<derived>());
}
}
SUBCASE("derived* to derived*") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.try_get_as<derived*>()->l == 168);
CHECK(v.try_get_as<const derived*>()->l == 168);
CHECK_FALSE(v.try_get_as<derived2*>());
CHECK_FALSE(v.try_get_as<const derived2*>());
}
{
const derived d{};
meta::uvalue v{&d};
CHECK(v.try_get_as<const derived*>()->l == 168);
CHECK_FALSE(v.try_get_as<const derived2*>());
}
}
SUBCASE("derived* to base*") {
{
derived d{};
meta::uvalue v{&d};
CHECK(v.try_get_as<base2*>()->k == 84);
CHECK(v.try_get_as<const base2*>()->k == 84);
}
{
const derived d{};
meta::uvalue v{&d};
CHECK_FALSE(v.try_get_as<base2*>());
CHECK(v.try_get_as<const base2*>()->k == 84);
}
}
}

View File

@@ -0,0 +1,262 @@
/*******************************************************************************
* 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 clazz_throw_dtor {
int i{};
[[maybe_unused]]
clazz_throw_dtor() {
++constructor_counter;
}
[[maybe_unused]]
clazz_throw_dtor(int ni) : i{ni} {
++constructor_counter;
}
[[maybe_unused]]
clazz_throw_dtor(clazz_throw_dtor&& other)
: i{other.i} {
other.i = 0;
++move_constructor_counter;
}
[[maybe_unused]]
clazz_throw_dtor(const clazz_throw_dtor& other)
: i{other.i} {
++copy_constructor_counter;
}
~clazz_throw_dtor() noexcept(false) {
++destructor_counter;
}
static clazz_throw_dtor make(int ni) {
return {ni};
}
inline static int destructor_counter{};
inline static int constructor_counter{};
inline static int move_constructor_counter{};
inline static int copy_constructor_counter{};
};
}
TEST_CASE("meta/meta_utilities/value5") {
namespace meta = meta_hpp;
meta::class_<clazz_throw_dtor>()
.function_("make", &clazz_throw_dtor::make);
}
TEST_CASE("meta/meta_utilities/value5/throw_dtor") {
namespace meta = meta_hpp;
SUBCASE("value") {
meta::uvalue v{clazz_throw_dtor{42}};
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 42);
}
SUBCASE("ptr_deref") {
clazz_throw_dtor obj{42};
meta::uvalue v_ptr{&obj};
CHECK(v_ptr.get_type() == meta::resolve_type<clazz_throw_dtor*>());
CHECK(v_ptr.get_as<clazz_throw_dtor*>() == &obj);
meta::uvalue v = *v_ptr;
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 42);
}
SUBCASE("array_index") {
clazz_throw_dtor objs[2]{42, 21};
meta::uvalue v_ptr{objs};
CHECK(v_ptr.get_type() == meta::resolve_type<clazz_throw_dtor*>());
CHECK(v_ptr.get_as<clazz_throw_dtor*>() == objs);
meta::uvalue v = v_ptr[1];
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 21);
}
SUBCASE("as_return_value") {
meta::class_type clazz_throw_dtor_type = meta::resolve_type<clazz_throw_dtor>();
meta::function clazz_throw_dtor_make_function = clazz_throw_dtor_type.get_function("make");
meta::uvalue v{clazz_throw_dtor_make_function(42)};
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 42);
}
}
TEST_CASE("meta/meta_utilities/value5/inplace") {
namespace meta = meta_hpp;
clazz_throw_dtor::destructor_counter = 0;
clazz_throw_dtor::constructor_counter = 0;
clazz_throw_dtor::move_constructor_counter = 0;
clazz_throw_dtor::copy_constructor_counter = 0;
SUBCASE("def") {
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>();
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 0);
CHECK(clazz_throw_dtor::destructor_counter == 0);
CHECK(clazz_throw_dtor::constructor_counter == 1);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 0);
}
SUBCASE("args") {
meta::uvalue v = meta::make_uvalue<std::vector<clazz_throw_dtor>>(2, 42);
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
CHECK(v[0].get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v[0].get_as<clazz_throw_dtor>().i == 42);
CHECK(v[1].get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v[1].get_as<clazz_throw_dtor>().i == 42);
}
SUBCASE("args/counters") {
{
meta::uvalue v = meta::make_uvalue<std::vector<clazz_throw_dtor>>(2, 42);
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
}
CHECK(clazz_throw_dtor::destructor_counter == 3);
CHECK(clazz_throw_dtor::constructor_counter == 1);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 2);
}
SUBCASE("ilist/1") {
meta::uvalue v = meta::make_uvalue<std::vector<int>>({21, 42});
CHECK(v.get_type() == meta::resolve_type<std::vector<int>>());
CHECK(v[0].get_type() == meta::resolve_type<int>());
CHECK(v[0].get_as<int>() == 21);
CHECK(v[1].get_type() == meta::resolve_type<int>());
CHECK(v[1].get_as<int>() == 42);
}
SUBCASE("ilist/2") {
meta::uvalue v = meta::make_uvalue<std::vector<int>>({21, 42}, std::allocator<int>{});
CHECK(v.get_type() == meta::resolve_type<std::vector<int, std::allocator<int>>>());
CHECK(v[0].get_type() == meta::resolve_type<int>());
CHECK(v[0].get_as<int>() == 21);
CHECK(v[1].get_type() == meta::resolve_type<int>());
CHECK(v[1].get_as<int>() == 42);
}
SUBCASE("ilist/counters") {
{
meta::uvalue v = meta::make_uvalue<std::vector<clazz_throw_dtor>>({
clazz_throw_dtor{21},
clazz_throw_dtor{42}});
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
}
CHECK(clazz_throw_dtor::destructor_counter == 4);
CHECK(clazz_throw_dtor::constructor_counter == 2);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 2);
}
}
TEST_CASE("meta/meta_utilities/value5/emplace") {
namespace meta = meta_hpp;
clazz_throw_dtor::destructor_counter = 0;
clazz_throw_dtor::constructor_counter = 0;
clazz_throw_dtor::move_constructor_counter = 0;
clazz_throw_dtor::copy_constructor_counter = 0;
SUBCASE("def") {
{
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(21);
CHECK(v.emplace<clazz_throw_dtor>().i == 0);
CHECK(v.get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v.get_as<clazz_throw_dtor>().i == 0);
}
CHECK(clazz_throw_dtor::destructor_counter == 2);
CHECK(clazz_throw_dtor::constructor_counter == 2);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 0);
}
SUBCASE("args") {
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(21);
v.emplace<std::vector<clazz_throw_dtor>>(2, 42);
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
CHECK(v[0].get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v[0].get_as<clazz_throw_dtor>().i == 42);
CHECK(v[1].get_type() == meta::resolve_type<clazz_throw_dtor>());
CHECK(v[1].get_as<clazz_throw_dtor>().i == 42);
}
SUBCASE("args/counters") {
{
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(21);
v.emplace<std::vector<clazz_throw_dtor>>(2, 42);
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
}
CHECK(clazz_throw_dtor::destructor_counter == 4);
CHECK(clazz_throw_dtor::constructor_counter == 2);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 2);
}
SUBCASE("ilist/1") {
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(84);
v.emplace<std::vector<int>>({21, 42});
CHECK(v.get_type() == meta::resolve_type<std::vector<int>>());
CHECK(v[0].get_type() == meta::resolve_type<int>());
CHECK(v[0].get_as<int>() == 21);
CHECK(v[1].get_type() == meta::resolve_type<int>());
CHECK(v[1].get_as<int>() == 42);
}
SUBCASE("ilist/2") {
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(84);
v.emplace<std::vector<int>>({21, 42}, std::allocator<int>{});
CHECK(v.get_type() == meta::resolve_type<std::vector<int, std::allocator<int>>>());
CHECK(v[0].get_type() == meta::resolve_type<int>());
CHECK(v[0].get_as<int>() == 21);
CHECK(v[1].get_type() == meta::resolve_type<int>());
CHECK(v[1].get_as<int>() == 42);
}
SUBCASE("ilist/counters") {
{
meta::uvalue v = meta::make_uvalue<clazz_throw_dtor>(84);
v.emplace<std::vector<clazz_throw_dtor>>({
clazz_throw_dtor{21},
clazz_throw_dtor{42}});
CHECK(v.get_type() == meta::resolve_type<std::vector<clazz_throw_dtor>>());
}
CHECK(clazz_throw_dtor::destructor_counter == 5);
CHECK(clazz_throw_dtor::constructor_counter == 3);
CHECK(clazz_throw_dtor::move_constructor_counter == 0);
CHECK(clazz_throw_dtor::copy_constructor_counter == 2);
}
}

View File

@@ -0,0 +1,573 @@
/*******************************************************************************
* 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 ivec2 {
int x{};
int y{};
ivec2() = delete;
[[maybe_unused]] explicit ivec2(int nv): x{nv}, y{nv} {}
[[maybe_unused]] ivec2(int nx, int ny): x{nx}, y{ny} {}
[[maybe_unused]] ivec2(ivec2&& other) noexcept
: x{other.x}
, y{other.y} {
other.x = 0;
other.y = 0;
++move_constructor_counter;
}
[[maybe_unused]] ivec2(const ivec2& other) noexcept
: x{other.x}
, y{other.y} {
++copy_constructor_counter;
}
ivec2& add(const ivec2& other) {
x += other.x;
y += other.y;
return *this;
}
ivec2& operator=(ivec2&& other) = delete;
ivec2& operator=(const ivec2& other) = delete;
public:
static int move_constructor_counter;
static int copy_constructor_counter;
};
struct ivec3 {
int x{};
int y{};
int z{};
ivec3() = delete;
[[maybe_unused]] explicit ivec3(int nv): x{nv}, y{nv}, z{nv} {}
[[maybe_unused]] ivec3(int nx, int ny, int nz): x{nx}, y{ny}, z{nz} {}
};
int ivec2::move_constructor_counter{0};
int ivec2::copy_constructor_counter{0};
ivec2 iadd2(ivec2 l, ivec2 r) {
return {l.x + r.x, l.y + r.y};
}
[[maybe_unused]] bool operator<(const ivec2& l, const ivec2& r) noexcept {
return (l.x < r.x) || (l.x == r.x && l.y < r.y);
}
[[maybe_unused]] bool operator==(const ivec2& l, const ivec2& r) noexcept {
return l.x == r.x && l.y == r.y;
}
}
TEST_CASE("meta/meta_utilities/value/ivec2") {
namespace meta = meta_hpp;
meta::class_<ivec2>()
.constructor_<int>()
.constructor_<int, int>()
.constructor_<ivec2&&>()
.constructor_<const ivec2&>()
.member_("x", &ivec2::x)
.member_("y", &ivec2::y);
}
TEST_CASE("meta/meta_utilities/value/ivec3") {
namespace meta = meta_hpp;
meta::class_<ivec3>()
.constructor_<int>()
.constructor_<int, int, int>()
.constructor_<ivec3&&>()
.constructor_<const ivec3&>()
.member_("x", &ivec3::x)
.member_("y", &ivec3::y)
.member_("z", &ivec3::z);
}
TEST_CASE("meta/meta_utilities/value") {
namespace meta = meta_hpp;
using namespace std::string_literals;
ivec2::move_constructor_counter = 0;
ivec2::copy_constructor_counter = 0;
SUBCASE("cast types") {
static_assert(std::is_same_v<
decltype(std::declval<meta::uvalue&>().get_as<ivec2>()),
ivec2&>);
static_assert(std::is_same_v<
decltype(std::declval<meta::uvalue&&>().get_as<ivec2>()),
ivec2&>);
static_assert(std::is_same_v<
decltype(std::declval<const meta::uvalue&>().get_as<ivec2>()),
const ivec2&>);
static_assert(std::is_same_v<
decltype(std::declval<const meta::uvalue&&>().get_as<ivec2>()),
const ivec2&>);
}
SUBCASE("ivec2{}") {
{
meta::uvalue val{};
CHECK(!val);
CHECK_FALSE(val);
CHECK_FALSE(val.is_valid());
CHECK(val.data() == nullptr);
CHECK(std::as_const(val).data() == nullptr);
CHECK(std::as_const(val).cdata() == nullptr);
CHECK_FALSE(*val);
CHECK_FALSE(val[0]);
CHECK_FALSE(val.try_get_as<ivec2>());
CHECK_FALSE(std::as_const(val).try_get_as<ivec2>());
CHECK_THROWS(std::ignore = val.get_as<int>());
CHECK_THROWS(std::ignore = std::as_const(val).get_as<int>());
CHECK_THROWS(std::ignore = std::move(val).get_as<int>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<int>());
}
{
CHECK_FALSE(1 < meta::uvalue{});
CHECK(meta::uvalue{} < 1);
}
{
CHECK_FALSE(1 == meta::uvalue{});
CHECK_FALSE(meta::uvalue{} == 1);
}
{
CHECK(1 != meta::uvalue{});
CHECK(meta::uvalue{} != 1);
}
CHECK_FALSE(meta::uvalue{} == 0);
CHECK_FALSE(meta::uvalue{} == nullptr);
CHECK(meta::uvalue{}.get_type() == meta::resolve_type<void>());
}
SUBCASE("ivec2&") {
ivec2 v{1,2};
ivec2& vr = v;
meta::uvalue val{vr};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 1);
CHECK(val.get_type() == meta::resolve_type<ivec2>());
CHECK(*static_cast<const ivec2*>(val.data()) == vr);
CHECK(*static_cast<const ivec2*>(val.cdata()) == vr);
CHECK(*static_cast<const ivec2*>(std::as_const(val).data()) == vr);
CHECK(*static_cast<const ivec2*>(std::as_const(val).cdata()) == vr);
CHECK(val == ivec2{1,2});
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK_FALSE(val.try_get_as<ivec3>());
CHECK_FALSE(std::as_const(val).try_get_as<ivec3>());
}
SUBCASE("const ivec2&") {
const ivec2 v{1,2};
const ivec2& vr = v;
meta::uvalue val{vr};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 1);
CHECK(val.get_type() == meta::resolve_type<ivec2>());
CHECK(*static_cast<const ivec2*>(val.data()) == vr);
CHECK(*static_cast<const ivec2*>(val.cdata()) == vr);
CHECK(*static_cast<const ivec2*>(std::as_const(val).data()) == vr);
CHECK(*static_cast<const ivec2*>(std::as_const(val).cdata()) == vr);
CHECK(val == ivec2{1,2});
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK_FALSE(val.try_get_as<ivec3>());
CHECK_FALSE(std::as_const(val).try_get_as<ivec3>());
}
SUBCASE("ivec2&&") {
ivec2 v{1,2};
meta::uvalue val{std::move(v)};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
CHECK(val.get_type() == meta::resolve_type<ivec2>());
CHECK(val == ivec2{1,2});
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK_FALSE(val.try_get_as<ivec3>());
CHECK_FALSE(std::as_const(val).try_get_as<ivec3>());
}
SUBCASE("const ivec2&&") {
const ivec2 v{1,2};
meta::uvalue val{std::move(v)};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 1);
CHECK(val.get_type() == meta::resolve_type<ivec2>());
CHECK(val == ivec2{1,2});
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(val).get_as<ivec2>() == ivec2{1,2});
CHECK(std::move(std::as_const(val)).get_as<ivec2>() == ivec2{1,2});
CHECK_THROWS(std::ignore = val.get_as<ivec3>());
CHECK_THROWS(std::ignore = std::as_const(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(val).get_as<ivec3>());
CHECK_THROWS(std::ignore = std::move(std::as_const(val)).get_as<ivec3>());
CHECK(val.get_as<ivec2>() == ivec2{1,2});
CHECK(std::as_const(val).get_as<ivec2>() == ivec2{1,2});
CHECK_FALSE(val.try_get_as<ivec3>());
CHECK_FALSE(std::as_const(val).try_get_as<ivec3>());
}
SUBCASE("value(value&&)") {
ivec2 v{1,2};
meta::uvalue val_src{std::move(v)};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
meta::uvalue val_dst{std::move(val_src)};
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("value(const meta::value&)") {
const ivec2 v{1,2};
meta::uvalue val_src{v};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 1);
meta::uvalue val_dst{val_src};
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 2);
CHECK(val_src == ivec2{1,2});
CHECK(val_src.data() != val_dst.data());
}
SUBCASE("value& operator=(T&&)") {
meta::uvalue val{10};
val = 20;
CHECK(val == 20);
val = "hello"s;
CHECK(val == "hello"s);
}
SUBCASE("value& operator=(value&&)") {
meta::uvalue val_src1{"world"s};
meta::uvalue val_src2{ivec2{1,2}};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
meta::uvalue val_dst{"hello"s};
val_dst = std::move(val_src1);
CHECK(val_dst == "world"s);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
val_dst = std::move(val_src2);
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 3);
CHECK(ivec2::copy_constructor_counter == 0);
}
SUBCASE("value& operator=(const meta::value&)") {
meta::uvalue val_src1{"world"s};
meta::uvalue val_src2{ivec2{1,2}};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
meta::uvalue val_dst{"hello"s};
val_dst = val_src1;
CHECK(val_dst == "world"s);
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
val_dst = val_src2;
CHECK(val_dst == ivec2{1,2});
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 1);
CHECK(val_src2 == ivec2{1,2});
CHECK(val_src2.data() != val_dst.data());
}
SUBCASE("swap") {
meta::uvalue val1{"world"s};
meta::uvalue val2{ivec2{1,2}};
CHECK(ivec2::move_constructor_counter == 1);
CHECK(ivec2::copy_constructor_counter == 0);
val1.swap(val2);
CHECK(val1 == ivec2{1,2});
CHECK(val2 == "world"s);
CHECK(ivec2::move_constructor_counter == 2);
CHECK(ivec2::copy_constructor_counter == 0);
swap(val1, val2);
CHECK(val1 == "world"s);
CHECK(val2 == ivec2{1,2});
}
SUBCASE("ostream") {
std::stringstream str_stream;
CHECK_NOTHROW(str_stream << meta::uvalue{21} << " " << meta::uvalue{42});
CHECK_THROWS((str_stream << meta::uvalue{ivec2{1,2}}));
REQUIRE(str_stream.str() == "21 42");
}
SUBCASE("istream") {
std::stringstream str_stream{"21 42"};
meta::uvalue v{ivec2{1,2}};
CHECK_THROWS(str_stream >> v);
v = meta::uvalue{0};
CHECK_NOTHROW(str_stream >> v);
CHECK(v == 21);
CHECK_NOTHROW(str_stream >> v);
CHECK(v == 42);
}
SUBCASE("operator<") {
CHECK(meta::uvalue{ivec2{1,2}} < ivec2{1,3});
CHECK_FALSE(meta::uvalue{ivec2{1,3}} < ivec2{1,2});
CHECK(ivec2{1,2} < meta::uvalue{ivec2{1,3}});
CHECK_FALSE(ivec2{1,3} < meta::uvalue{ivec2{1,2}});
}
SUBCASE("operator==") {
CHECK(meta::uvalue{ivec2{1,2}} == ivec2{1,2});
CHECK_FALSE(meta::uvalue{ivec2{1,2}} == ivec2{1,3});
CHECK(ivec2{1,2} == meta::uvalue{ivec2{1,2}});
CHECK_FALSE(ivec2{1,3} == meta::uvalue{ivec2{1,2}});
}
SUBCASE("deref") {
{
int i{42};
const meta::uvalue v{*meta::uvalue{&i}};
CHECK(v.get_type() == meta::resolve_type<int>());
CHECK(v.data() != &i);
}
{
const char i{42};
const meta::uvalue v{*meta::uvalue{&i}};
CHECK(v.get_type() == meta::resolve_type<char>());
CHECK(v.data() != &i);
}
{
const int i{42};
const int* const pi = &i;
const meta::uvalue v{*meta::uvalue{&pi}};
CHECK(v.get_type() == meta::resolve_type<const int*>() );
CHECK(v.get_as<const int*>() == pi);
}
{
int i{42};
void* p1 = &i;
const void* p2 = &i;
void* const& p3 = &i;
const void* const& p4 = &i;
CHECK_THROWS(std::ignore = *meta::uvalue(p1));
CHECK_THROWS(std::ignore = *meta::uvalue(p2));
CHECK_THROWS(std::ignore = *meta::uvalue(p3));
CHECK_THROWS(std::ignore = *meta::uvalue(p4));
}
{
ivec2 v{1,2};
meta::uvalue vp{&v};
CHECK(ivec2::move_constructor_counter == 0);
CHECK(ivec2::copy_constructor_counter == 0);
[[maybe_unused]] meta::uvalue vv1{*vp};
CHECK((ivec2::move_constructor_counter == 0 || ivec2::move_constructor_counter == 1 || ivec2::move_constructor_counter == 2));
CHECK(ivec2::copy_constructor_counter == 1);
[[maybe_unused]] meta::uvalue vv2{*std::move(vp)};
CHECK((ivec2::move_constructor_counter == 0 || ivec2::move_constructor_counter == 2 || ivec2::move_constructor_counter == 4));
CHECK(ivec2::copy_constructor_counter == 2);
[[maybe_unused]] meta::uvalue vv3{*std::as_const(vp)};
CHECK((ivec2::move_constructor_counter == 0 || ivec2::move_constructor_counter == 3 || ivec2::move_constructor_counter == 6));
CHECK(ivec2::copy_constructor_counter == 3);
}
{
meta::uvalue v{std::make_shared<int>(42)};
CHECK(*v == 42);
}
}
}
TEST_CASE("meta/meta_utilities/value/arrays") {
namespace meta = meta_hpp;
SUBCASE("int[3]") {
int arr[3]{1,2,3};
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<int*>());
CHECK(v[0] == 1);
CHECK(v[1] == 2);
CHECK(v[2] == 3);
}
SUBCASE("const int[3]") {
const int arr[3]{1,2,3};
meta::uvalue v{arr};
CHECK(v.get_type() == meta::resolve_type<const int*>());
CHECK(v[0] == 1);
CHECK(v[1] == 2);
CHECK(v[2] == 3);
}
SUBCASE("std::array") {
meta::uvalue v{std::array{1,2,3}};
CHECK(v.get_type() == meta::resolve_type<std::array<int, 3>>());
CHECK(v[0] == 1);
CHECK(v[1] == 2);
CHECK(v[2] == 3);
}
SUBCASE("std::string") {
meta::uvalue v{std::string{"hi!"}};
CHECK(v.get_type() == meta::resolve_type<std::string>());
CHECK(v[0] == 'h');
CHECK(v[1] == 'i');
CHECK(v[2] == '!');
}
SUBCASE("std::span") {
std::vector arr{1,2,3};
meta::uvalue v{std::span{arr}};
CHECK(v.get_type() == meta::resolve_type<std::span<int>>());
CHECK(v[0] == 1);
CHECK(v[1] == 2);
CHECK(v[2] == 3);
}
SUBCASE("std::vector") {
const meta::uvalue v{std::vector{1,2,3}};
CHECK(v.get_type() == meta::resolve_type<std::vector<int>>());
CHECK(v[0] == 1);
CHECK(v[1] == 2);
CHECK(v[2] == 3);
}
}
TEST_CASE("meta/meta_utilities/value/functions") {
namespace meta = meta_hpp;
SUBCASE("add") {
{
meta::uvalue v{&ivec2::add};
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
CHECK(v.get_as<decltype(&ivec2::add)>() == &ivec2::add);
CHECK((ivec2{1,2}.*(v.get_as<decltype(&ivec2::add)>()))(ivec2{3,4}) == ivec2(4,6));
}
{
const meta::uvalue v{&ivec2::add};
CHECK(v.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
CHECK(v.get_as<decltype(&ivec2::add)>() == &ivec2::add);
CHECK((ivec2{1,2}.*(v.get_as<decltype(&ivec2::add)>()))(ivec2{3,4}) == ivec2(4,6));
}
}
SUBCASE("iadd2") {
{
meta::uvalue v{iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK((v.get_as<decltype(&iadd2)>() == &iadd2));
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
{
meta::uvalue v{&iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK((v.get_as<decltype(&iadd2)>() == &iadd2));
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
{
const meta::uvalue v{iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK((v.get_as<decltype(&iadd2)>() == &iadd2));
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
{
const meta::uvalue v{&iadd2};
CHECK(v.get_type() == meta::resolve_type<ivec2(*)(ivec2, ivec2)>());
CHECK((v.get_as<decltype(&iadd2)>() == &iadd2));
CHECK((v.get_as<decltype(&iadd2)>())(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
}
}