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.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)

View 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);
}

View 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);
}

View 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;
}
}

View 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());
}

View 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);
}

View 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});
}

View 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);
}

View 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 = &rect;
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);
}
}

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_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;
}
}

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>