mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 19:41:29 +07:00
hide all developer stuff to develop directory
This commit is contained in:
18
develop/manuals/.clang-tidy
Normal file
18
develop/manuals/.clang-tidy
Normal 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-*,
|
||||
'
|
||||
...
|
||||
80
develop/manuals/CMakeLists.txt
Normal file
80
develop/manuals/CMakeLists.txt
Normal file
@@ -0,0 +1,80 @@
|
||||
project(meta.hpp.manuals)
|
||||
|
||||
file(GLOB_RECURSE MANUALS_SOURCES "*.cpp" "*.hpp")
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${MANUALS_SOURCES})
|
||||
|
||||
add_executable(${PROJECT_NAME} ${MANUALS_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp::meta.hpp)
|
||||
|
||||
add_executable(${PROJECT_NAME}.singles ${MANUALS_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)
|
||||
81
develop/manuals/meta_examples/class_example.cpp
Normal file
81
develop/manuals/meta_examples/class_example.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class shape {
|
||||
public:
|
||||
shape() = default;
|
||||
shape(const shape&) = default;
|
||||
virtual ~shape() = default;
|
||||
|
||||
virtual int get_area() const = 0;
|
||||
};
|
||||
|
||||
class rectangle : public shape {
|
||||
public:
|
||||
explicit rectangle(int width, int height)
|
||||
: width_{width}
|
||||
, height_{height} {}
|
||||
|
||||
int get_width() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
int get_height() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
int get_area() const override {
|
||||
return width_ * height_;
|
||||
}
|
||||
private:
|
||||
int width_{};
|
||||
int height_{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/class/type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'shape' class type registration
|
||||
meta::class_<shape>()
|
||||
.method_("get_area", &shape::get_area);
|
||||
|
||||
// 'rectangle' class type registration
|
||||
meta::class_<rectangle>()
|
||||
.base_<shape>()
|
||||
.constructor_<int, int>()
|
||||
.method_("get_width", &rectangle::get_width)
|
||||
.method_("get_height", &rectangle::get_height);
|
||||
|
||||
// resolves a class type by static class type
|
||||
const meta::class_type rectangle_type = meta::resolve_type<rectangle>();
|
||||
|
||||
// prints all class methods
|
||||
std::cout << "* rectangle" << std::endl;
|
||||
for ( auto&& [index, method] : rectangle_type.get_methods() ) {
|
||||
std::cout << " + " << index.get_name() << "/" << index.get_type().get_arity() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/class/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// resolves a class type by static class type
|
||||
const meta::class_type rectangle_type = meta::resolve_type<rectangle>();
|
||||
|
||||
// finds the method 'get_area' by name
|
||||
const meta::method rectangle_area = rectangle_type.get_method("get_area");
|
||||
|
||||
// creates a rectangle instance by the registered constructor(int, int)
|
||||
const meta::uvalue rectangle_v = rectangle_type.create(10, 20);
|
||||
|
||||
// calls the method with the dynamic rectangle instance 'rectangle_v'
|
||||
CHECK(rectangle_area.invoke(rectangle_v) == 200);
|
||||
}
|
||||
56
develop/manuals/meta_examples/enum_example.cpp
Normal file
56
develop/manuals/meta_examples/enum_example.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class align {
|
||||
left,
|
||||
right,
|
||||
center,
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/enum/type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'align' enumeration type registration
|
||||
meta::enum_<align>()
|
||||
.evalue_("left", align::left)
|
||||
.evalue_("right", align::right)
|
||||
.evalue_("center", align::center);
|
||||
|
||||
// resolves a enumeration type by enumerator
|
||||
const meta::enum_type align_type = meta::resolve_type(align::left);
|
||||
|
||||
// also, it can be resolved by static enumeration type
|
||||
CHECK(align_type == meta::resolve_type<align>());
|
||||
|
||||
// allows to know the underlying type
|
||||
CHECK(align_type.get_underlying_type() == meta::resolve_type<int>());
|
||||
|
||||
// prints all enumerators
|
||||
std::cout << "* align" << std::endl;
|
||||
for ( auto&& [index, evalue] : align_type.get_evalues() ) {
|
||||
std::cout << " - " << index.get_name() << "/" << evalue.get_underlying_value() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/enum/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
const align e = align::center;
|
||||
|
||||
// resolves a enumeration type by enumerator instance 'e'
|
||||
const meta::enum_type align_type = meta::resolve_type(e);
|
||||
|
||||
// converts the enumerator to its name
|
||||
CHECK(align_type.value_to_name(e) == "center");
|
||||
|
||||
// ... and back again
|
||||
CHECK(align_type.name_to_value("center") == e);
|
||||
}
|
||||
78
develop/manuals/meta_examples/function_example.cpp
Normal file
78
develop/manuals/meta_examples/function_example.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int sub(int a, int b) {
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/function/type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// resolves a function type by pointer
|
||||
const meta::function_type add_function_type = meta::resolve_type(&add);
|
||||
|
||||
// also, it can be resolved by static function type declaration
|
||||
CHECK(add_function_type == meta::resolve_type<int(*)(int, int)>());
|
||||
|
||||
// checks a return value type
|
||||
CHECK(add_function_type.get_return_type() == meta::resolve_type<int>());
|
||||
|
||||
// allows to know an argument count
|
||||
CHECK(add_function_type.get_arity() == 2);
|
||||
|
||||
// ... and their types
|
||||
CHECK(add_function_type.get_argument_type(0) == meta::resolve_type<int>());
|
||||
CHECK(add_function_type.get_argument_type(1) == meta::resolve_type<int>());
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/function/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'math' local scope declaration
|
||||
const meta::scope math_scope = meta::local_scope_("math")
|
||||
.function_("add", &add)
|
||||
.function_("sub", &sub);
|
||||
|
||||
// finds the function by name 'sub'
|
||||
const meta::function sub_function = math_scope.get_function("sub");
|
||||
|
||||
// also, we can find it with argument types (for overloaded functions)
|
||||
CHECK(sub_function == math_scope.get_function_with<int, int>("sub"));
|
||||
|
||||
// checks a type of the found function
|
||||
CHECK(sub_function.get_type() == meta::resolve_type<int(*)(int, int)>());
|
||||
|
||||
// checks the ability to call the function with specific arguments
|
||||
CHECK(sub_function.is_invocable_with(60, 18));
|
||||
CHECK(sub_function.is_invocable_with<int, int>());
|
||||
|
||||
// calls the function and retrieves a returned value
|
||||
const meta::uvalue sub_result_value = sub_function.invoke(60, 18);
|
||||
|
||||
// checks the type of the returned value
|
||||
CHECK(sub_result_value.get_type() == meta::resolve_type<int>());
|
||||
|
||||
// casts the dynamic returned value to the typed value
|
||||
const int sub_function_typed_result = sub_result_value.get_as<int>();
|
||||
|
||||
// here is our typed result
|
||||
CHECK(sub_function_typed_result == 42);
|
||||
|
||||
// prints all functions in the scope
|
||||
std::cout << "* " << math_scope.get_name() << std::endl;
|
||||
for ( auto&& [index, function] : math_scope.get_functions() ) {
|
||||
std::cout << " + " << index.get_name() << "/" << function.get_type().get_arity() << std::endl;
|
||||
}
|
||||
}
|
||||
66
develop/manuals/meta_examples/inplace_example.cpp
Normal file
66
develop/manuals/meta_examples/inplace_example.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x;
|
||||
int y;
|
||||
|
||||
explicit ivec2(int nv) : x{nv}, y{nv} {}
|
||||
ivec2(int nx, int ny) : x{nx}, y{ny} {}
|
||||
|
||||
int length2() const noexcept {
|
||||
return x * x + y * y;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/inplace") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'ivec2' class type registration
|
||||
meta::class_<ivec2>()
|
||||
.constructor_<int>()
|
||||
.constructor_<int, int>()
|
||||
.member_("x", &ivec2::x)
|
||||
.member_("y", &ivec2::y)
|
||||
.method_("length2", &ivec2::length2);
|
||||
|
||||
// creates local scope for finding types by name
|
||||
const meta::scope math_scope = meta::local_scope_("math")
|
||||
.typedef_<ivec2>("ivec2");
|
||||
|
||||
// finds required types/members/methods
|
||||
const meta::class_type ivec2_type = math_scope.get_typedef("ivec2").as_class();
|
||||
const meta::member ivec2_x = ivec2_type.get_member("x");
|
||||
const meta::member ivec2_y = ivec2_type.get_member("y");
|
||||
const meta::method ivec2_length2 = ivec2_type.get_method("length2");
|
||||
|
||||
// allocates dynamic memory buffer with required size and alignment
|
||||
meta::memory_buffer ivec2_buffer{
|
||||
ivec2_type.get_size(),
|
||||
std::align_val_t{ivec2_type.get_align()}};
|
||||
|
||||
// or you can use static buffer instead (if the required type is available at compile-time)
|
||||
// alignas(ivec2) std::byte ivec2_buffer[sizeof(ivec2)];
|
||||
|
||||
// creates 'ivec2' on the memory buffer ('placement new' under the hood)
|
||||
const meta::uvalue ivec2_ptr = ivec2_type.create_at(ivec2_buffer.get_memory(), 2, 3);
|
||||
|
||||
// 'create_at' returns a pointer to the constructed object
|
||||
CHECK(ivec2_ptr.get_type() == meta::resolve_type<ivec2*>());
|
||||
|
||||
// interacts with the created object as usual
|
||||
CHECK(ivec2_x.get(ivec2_ptr) == 2);
|
||||
CHECK(ivec2_y.get(ivec2_ptr) == 3);
|
||||
CHECK(ivec2_length2(ivec2_ptr) == 13);
|
||||
|
||||
// you must manually call the object's destructor
|
||||
ivec2_type.destroy_at(ivec2_buffer.get_memory());
|
||||
}
|
||||
69
develop/manuals/meta_examples/member_example.cpp
Normal file
69
develop/manuals/meta_examples/member_example.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/member/type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'ivec2' class type registration
|
||||
meta::class_<ivec2>()
|
||||
.member_("x", &ivec2::x)
|
||||
.member_("y", &ivec2::y);
|
||||
|
||||
// resolves a member type by pointer
|
||||
const meta::member_type x_member_type = meta::resolve_type(&ivec2::x);
|
||||
|
||||
// also, it can be resolved by static member type
|
||||
CHECK(x_member_type == meta::resolve_type<int ivec2::*>());
|
||||
|
||||
// allows to know the owner class type
|
||||
CHECK(x_member_type.get_owner_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
// ... and the value type of the member
|
||||
CHECK(x_member_type.get_value_type() == meta::resolve_type<int>());
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/member/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
ivec2 v{42, 21};
|
||||
|
||||
// resolves a class type by instance 'v'
|
||||
const meta::class_type ivec2_type = meta::resolve_type(v);
|
||||
|
||||
// finds the member 'x' by name
|
||||
const meta::member ivec2_x = ivec2_type.get_member("x");
|
||||
|
||||
// checks the type of the member 'x'
|
||||
CHECK(ivec2_x.get_type() == meta::resolve_type<int ivec2::*>());
|
||||
|
||||
// retrieves a member value of the class instance 'v'
|
||||
const meta::uvalue ivec2_x_value = ivec2_x.get(v);
|
||||
|
||||
// checks the type of the retrieved value
|
||||
CHECK(ivec2_x_value.get_type() == meta::resolve_type<int>());
|
||||
|
||||
// casts the dynamic value to the typed value
|
||||
const int ivec2_x_typed_value = ivec2_x_value.get_as<int>();
|
||||
|
||||
// here is our member typed value
|
||||
CHECK(ivec2_x_typed_value == 42);
|
||||
|
||||
// also, we can change the member value, of course
|
||||
ivec2_x.set(v, 11);
|
||||
|
||||
// checks the result of our manipulations
|
||||
CHECK(v.x == 11);
|
||||
}
|
||||
80
develop/manuals/meta_examples/method_example.cpp
Normal file
80
develop/manuals/meta_examples/method_example.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
ivec2& add(const ivec2& other) {
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const ivec2& l, const ivec2& r) {
|
||||
return l.x == r.x && l.y == r.y;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/method/type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'ivec2' class type registration
|
||||
meta::class_<ivec2>()
|
||||
.method_("add", &ivec2::add);
|
||||
|
||||
// resolves a method type by pointer
|
||||
const meta::method_type add_method_type = meta::resolve_type(&ivec2::add);
|
||||
|
||||
// also, it can be resolved by static method type
|
||||
CHECK(add_method_type == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
|
||||
|
||||
// allows to know the owner class type
|
||||
CHECK(add_method_type.get_owner_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
// checks a return value type
|
||||
CHECK(add_method_type.get_return_type() == meta::resolve_type<ivec2&>());
|
||||
|
||||
// allows to know an argument count
|
||||
CHECK(add_method_type.get_arity() == 1);
|
||||
|
||||
// ... and their types
|
||||
CHECK(add_method_type.get_argument_type(0) == meta::resolve_type<const ivec2&>());
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/method/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
ivec2 v{20, 10};
|
||||
|
||||
// resolves a class type by instance 'v'
|
||||
const meta::class_type ivec2_type = meta::resolve_type(v);
|
||||
|
||||
// finds the method 'add' by name
|
||||
const meta::method ivec2_add = ivec2_type.get_method("add");
|
||||
|
||||
// checks the type of the method 'add'
|
||||
CHECK(ivec2_add.get_type() == meta::resolve_type<ivec2&(ivec2::*)(const ivec2&)>());
|
||||
|
||||
// checks the ability to call the method with specific arguments
|
||||
CHECK(ivec2_add.is_invocable_with(v, ivec2{22, 11}));
|
||||
CHECK(ivec2_add.is_invocable_with<ivec2&, ivec2>());
|
||||
|
||||
// calls the method and retrieves a returned value
|
||||
const meta::uvalue ivec2_add_result_value = ivec2_add.invoke(v, ivec2{22, 11});
|
||||
|
||||
// checks the type and value of the result
|
||||
CHECK(ivec2_add_result_value.get_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(ivec2_add_result_value == ivec2{42, 21});
|
||||
|
||||
// checks the result of our manipulations
|
||||
CHECK(v == ivec2{42, 21});
|
||||
}
|
||||
111
develop/manuals/meta_examples/scopes_example.cpp
Normal file
111
develop/manuals/meta_examples/scopes_example.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{}, y{};
|
||||
};
|
||||
|
||||
struct ivec3 {
|
||||
int x{}, y{}, z{};
|
||||
};
|
||||
|
||||
const ivec2 unit2{1, 1};
|
||||
const ivec3 unit3{1, 1, 1};
|
||||
|
||||
[[maybe_unused]]
|
||||
int dot2(const ivec2& a, const ivec2& b) {
|
||||
return a.x * b.x
|
||||
+ a.y * b.y;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
int dot3(const ivec3& a, const ivec3& b) {
|
||||
return a.x * b.x
|
||||
+ a.y * b.y
|
||||
+ a.z * b.z;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
bool operator==(const ivec2& a, const ivec2& b) {
|
||||
return a.x == b.x
|
||||
&& a.y == b.y;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
bool operator==(const ivec3& a, const ivec3& b) {
|
||||
return a.x == b.x
|
||||
&& a.y == b.y
|
||||
&& a.z == b.z;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/scopes/local") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// creates new local scope
|
||||
// you can use it inplace or store anywhere to use it later
|
||||
const meta::scope math_scope = meta::local_scope_("math")
|
||||
.typedef_<ivec2>("ivec2")
|
||||
.typedef_<ivec3>("ivec3")
|
||||
.function_("dot2", &dot2)
|
||||
.function_("dot3", &dot3)
|
||||
.variable_("unit2", &unit2)
|
||||
.variable_("unit3", &unit3);
|
||||
|
||||
// finds types by names
|
||||
const meta::class_type ivec2_type = math_scope.get_typedef("ivec2").as_class();
|
||||
const meta::class_type ivec3_type = math_scope.get_typedef("ivec3").as_class();
|
||||
|
||||
// checks found types
|
||||
CHECK(ivec2_type == meta::resolve_type<ivec2>());
|
||||
CHECK(ivec3_type == meta::resolve_type<ivec3>());
|
||||
|
||||
// similarly, we can find free functions by name
|
||||
const meta::function dot2_function = math_scope.get_function("dot2");
|
||||
const meta::function dot3_function = math_scope.get_function("dot3");
|
||||
|
||||
// calls and checks found functions
|
||||
CHECK(dot2_function(ivec2{3,4}, ivec2{5,6}) == 39);
|
||||
CHECK(dot3_function(ivec3{3,4,5}, ivec3{6,7,8}) == 86);
|
||||
|
||||
// and free variables, of course
|
||||
const meta::variable unit2_variable = math_scope.get_variable("unit2");
|
||||
const meta::variable unit3_variable = math_scope.get_variable("unit3");
|
||||
|
||||
// checks and uses found variables with functions
|
||||
CHECK(unit2_variable.get() == ivec2{1,1});
|
||||
CHECK(unit3_variable.get() == ivec3{1,1,1});
|
||||
CHECK(dot2_function(unit2_variable.get(), unit2_variable.get()) == 2);
|
||||
CHECK(dot3_function(unit3_variable.get(), unit3_variable.get()) == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/scopes/global") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// also, we can create global scopes
|
||||
meta::static_scope_("meta/meta_examples/scopes/global/math")
|
||||
.function_("dot2", &dot2)
|
||||
.function_("dot3", &dot3)
|
||||
.variable_("unit2", &unit2)
|
||||
.variable_("unit3", &unit3);
|
||||
|
||||
// finds our global scope by name
|
||||
const meta::scope math_scope = meta::resolve_scope("meta/meta_examples/scopes/global/math");
|
||||
|
||||
// and uses it in the same way
|
||||
const meta::function dot2_function = math_scope.get_function("dot2");
|
||||
const meta::function dot3_function = math_scope.get_function("dot3");
|
||||
const meta::variable unit2_variable = math_scope.get_variable("unit2");
|
||||
const meta::variable unit3_variable = math_scope.get_variable("unit3");
|
||||
|
||||
// everything works as expected
|
||||
CHECK(dot2_function(unit2_variable.get(), unit2_variable.get()) == 2);
|
||||
CHECK(dot3_function(unit3_variable.get(), unit3_variable.get()) == 3);
|
||||
}
|
||||
98
develop/manuals/meta_examples/uvalue_example.cpp
Normal file
98
develop/manuals/meta_examples/uvalue_example.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*******************************************************************************
|
||||
* 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class shape {
|
||||
public:
|
||||
shape() = default;
|
||||
shape(const shape&) = default;
|
||||
virtual ~shape() = default;
|
||||
|
||||
virtual int get_area() const = 0;
|
||||
};
|
||||
|
||||
class rectangle : public shape {
|
||||
public:
|
||||
explicit rectangle(int width, int height)
|
||||
: width_{width}
|
||||
, height_{height} {}
|
||||
|
||||
int get_width() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
int get_height() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
int get_area() const override {
|
||||
return width_ * height_;
|
||||
}
|
||||
private:
|
||||
int width_{};
|
||||
int height_{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/uvalue") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'shape' class type registration
|
||||
meta::class_<shape>()
|
||||
.method_("get_area", &shape::get_area);
|
||||
|
||||
// 'rectangle' class type registration
|
||||
meta::class_<rectangle>()
|
||||
.base_<shape>()
|
||||
.constructor_<int, int>()
|
||||
.method_("get_width", &rectangle::get_width)
|
||||
.method_("get_height", &rectangle::get_height);
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/uvalue/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// the 'uvalue' class allows to store any copyable value inside
|
||||
// it's widely used as return value types and as containers for storing metadata
|
||||
|
||||
meta::uvalue val{42};
|
||||
CHECK(val.get_type() == meta::resolve_type<int>());
|
||||
|
||||
// we can get a reference to the stored data and even change it
|
||||
val.get_as<int>() = 21;
|
||||
CHECK(val.get_as<int>() == 21);
|
||||
|
||||
// uvalue can be copied, assigned, and moved
|
||||
val = rectangle{10, 20};
|
||||
CHECK(val.get_type() == meta::resolve_type<rectangle>());
|
||||
|
||||
// also, it supports upcasting for registered types
|
||||
CHECK(val.get_as<shape>().get_area() == 200);
|
||||
|
||||
// an exception will be thrown if we try to get a wrong type
|
||||
CHECK_THROWS(std::ignore = val.get_as<int>());
|
||||
|
||||
// but we can use try_get_as for safe access
|
||||
CHECK(val.try_get_as<shape>());
|
||||
if ( shape* s = val.try_get_as<shape>() ) {
|
||||
CHECK(s->get_area() == 200);
|
||||
}
|
||||
|
||||
// also, upcasting is supported for pointers
|
||||
rectangle rect{3, 5};
|
||||
val = ▭
|
||||
CHECK(val.get_as<shape*>()->get_area() == 15);
|
||||
CHECK(val.get_type() == meta::resolve_type<rectangle*>());
|
||||
|
||||
// and we can use try_get_as for pointers too
|
||||
CHECK(val.try_get_as<shape*>());
|
||||
if ( shape* s = val.try_get_as<shape*>() ) {
|
||||
CHECK(s->get_area() == 15);
|
||||
}
|
||||
}
|
||||
47
develop/manuals/meta_examples/variable_example.cpp
Normal file
47
develop/manuals/meta_examples/variable_example.cpp
Normal 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_manuals.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
const double pi_v{3.1415926536};
|
||||
const double sqrt2_v{1.4142135624};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_examples/variable/usage") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
// 'constants' local scope declaration
|
||||
const meta::scope constants_scope = meta::local_scope_("constants")
|
||||
.variable_("pi_v", &pi_v)
|
||||
.variable_("sqrt2_v", &sqrt2_v);
|
||||
|
||||
// finds the variable by name 'pi_v'
|
||||
const meta::variable pi_variable = constants_scope.get_variable("pi_v");
|
||||
|
||||
// checks the type and data type of the found variable
|
||||
CHECK(pi_variable.get_type() == meta::resolve_type<const double*>());
|
||||
CHECK(pi_variable.get_type().get_data_type() == meta::resolve_type<double>());
|
||||
|
||||
// retrieves a variable value
|
||||
const meta::uvalue pi_variable_value = pi_variable.get();
|
||||
|
||||
// checks the type of the retrieved value
|
||||
CHECK(pi_variable_value.get_type() == meta::resolve_type<double>());
|
||||
|
||||
// checks the typed variable value
|
||||
CHECK(pi_variable_value.get_as<double>() == doctest::Approx(3.14).epsilon(0.01));
|
||||
|
||||
// we can change variable values, but only non-const
|
||||
CHECK_THROWS(pi_variable.set(6.0));
|
||||
|
||||
// prints all variables in the scope
|
||||
std::cout << "* " << constants_scope.get_name() << std::endl;
|
||||
for ( auto&& [index, variable] : constants_scope.get_variables() ) {
|
||||
std::cout << " - " << index.get_name() << ":" << variable.get() << std::endl;
|
||||
}
|
||||
}
|
||||
11
develop/manuals/meta_manuals.hpp
Normal file
11
develop/manuals/meta_manuals.hpp
Normal 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>
|
||||
Reference in New Issue
Block a user