mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-16 22:17:02 +07:00
new basic version
This commit is contained in:
@@ -10,6 +10,20 @@
|
||||
|
||||
#include "meta_kinds.hpp"
|
||||
|
||||
#include "meta_registry.hpp"
|
||||
#include "meta_registry/class_bind.hpp"
|
||||
#include "meta_registry/enum_bind.hpp"
|
||||
#include "meta_registry/scope_bind.hpp"
|
||||
|
||||
#include "meta_states.hpp"
|
||||
#include "meta_states/ctor.hpp"
|
||||
#include "meta_states/evalue.hpp"
|
||||
#include "meta_states/function.hpp"
|
||||
#include "meta_states/member.hpp"
|
||||
#include "meta_states/method.hpp"
|
||||
#include "meta_states/scope.hpp"
|
||||
#include "meta_states/variable.hpp"
|
||||
|
||||
#include "meta_traits.hpp"
|
||||
#include "meta_traits/array_traits.hpp"
|
||||
#include "meta_traits/class_traits.hpp"
|
||||
@@ -22,3 +36,22 @@
|
||||
#include "meta_traits/pointer_traits.hpp"
|
||||
#include "meta_traits/reference_traits.hpp"
|
||||
#include "meta_traits/void_traits.hpp"
|
||||
|
||||
#include "meta_types.hpp"
|
||||
#include "meta_types/any_type.hpp"
|
||||
#include "meta_types/array_type.hpp"
|
||||
#include "meta_types/class_type.hpp"
|
||||
#include "meta_types/ctor_type.hpp"
|
||||
#include "meta_types/enum_type.hpp"
|
||||
#include "meta_types/function_type.hpp"
|
||||
#include "meta_types/member_type.hpp"
|
||||
#include "meta_types/method_type.hpp"
|
||||
#include "meta_types/number_type.hpp"
|
||||
#include "meta_types/pointer_type.hpp"
|
||||
#include "meta_types/reference_type.hpp"
|
||||
#include "meta_types/void_type.hpp"
|
||||
|
||||
#include "meta_utilities.hpp"
|
||||
#include "meta_utilities/arg.hpp"
|
||||
#include "meta_utilities/inst.hpp"
|
||||
#include "meta_utilities/value.hpp"
|
||||
|
||||
@@ -165,6 +165,7 @@ namespace meta_hpp
|
||||
struct function_index;
|
||||
struct member_index;
|
||||
struct method_index;
|
||||
struct scope_index;
|
||||
struct variable_index;
|
||||
|
||||
using class_set = std::set<class_type, std::less<>>;
|
||||
@@ -178,5 +179,6 @@ namespace meta_hpp
|
||||
using function_map = std::map<function_index, function, std::less<>>;
|
||||
using member_map = std::map<member_index, member, std::less<>>;
|
||||
using method_map = std::map<method_index, method, std::less<>>;
|
||||
using scope_map = std::map<scope_index, scope, std::less<>>;
|
||||
using variable_map = std::map<variable_index, variable, std::less<>>;
|
||||
}
|
||||
|
||||
94
headers/meta.hpp/meta_registry.hpp
Normal file
94
headers/meta.hpp/meta_registry.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "meta_base.hpp"
|
||||
#include "meta_states.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < class_kind Class >
|
||||
class class_bind final {
|
||||
public:
|
||||
explicit class_bind();
|
||||
operator class_type() const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
class_bind& ctor_();
|
||||
|
||||
template < class_kind Base >
|
||||
class_bind& base_();
|
||||
|
||||
template < function_kind Function >
|
||||
class_bind& function_(std::string name, Function function);
|
||||
|
||||
template < member_kind Member >
|
||||
class_bind& member_(std::string name, Member member);
|
||||
|
||||
template < method_kind Method >
|
||||
class_bind& method_(std::string name, Method method);
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
class_bind& variable_(std::string name, Pointer pointer);
|
||||
private:
|
||||
detail::class_type_data_ptr data_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < enum_kind Enum >
|
||||
class enum_bind final {
|
||||
public:
|
||||
explicit enum_bind();
|
||||
operator enum_type() const noexcept;
|
||||
|
||||
enum_bind& evalue_(std::string name, Enum value);
|
||||
private:
|
||||
detail::enum_type_data_ptr data_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class scope_bind final {
|
||||
public:
|
||||
explicit scope_bind(std::string_view name);
|
||||
operator scope() const noexcept;
|
||||
|
||||
template < class_kind Class >
|
||||
scope_bind& class_(std::string name);
|
||||
|
||||
template < enum_kind Enum >
|
||||
scope_bind& enum_(std::string name);
|
||||
|
||||
template < function_kind Function >
|
||||
scope_bind& function_(std::string name, Function function);
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
scope_bind& variable_(std::string name, Pointer pointer);
|
||||
private:
|
||||
detail::scope_state_ptr state_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < class_kind Class >
|
||||
class_bind<Class> class_() {
|
||||
return class_bind<Class>{};
|
||||
}
|
||||
|
||||
template < enum_kind Enum >
|
||||
enum_bind<Enum> enum_() {
|
||||
return enum_bind<Enum>{};
|
||||
}
|
||||
|
||||
inline scope_bind scope_(std::string name) {
|
||||
return scope_bind{std::move(name)};
|
||||
}
|
||||
}
|
||||
70
headers/meta.hpp/meta_registry/class_bind.hpp
Normal file
70
headers/meta.hpp/meta_registry/class_bind.hpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_registry.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < class_kind Class >
|
||||
class_bind<Class>::class_bind()
|
||||
: data_{detail::get_type_data<Class>()} {}
|
||||
|
||||
template < class_kind Class >
|
||||
class_bind<Class>::operator class_type() const noexcept {
|
||||
return class_type{data_};
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < typename... Args >
|
||||
class_bind<Class>& class_bind<Class>::ctor_() {
|
||||
auto ctor_state = detail::ctor_state::make<Class, Args...>();
|
||||
data_->ctors.emplace(ctor_state->index, std::move(ctor_state));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < class_kind Base >
|
||||
class_bind<Class>& class_bind<Class>::base_() {
|
||||
auto base_data = detail::class_type_data::get<Base>();
|
||||
data_->bases.emplace(base_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < function_kind Function >
|
||||
class_bind<Class>& class_bind<Class>::function_(std::string name, Function function) {
|
||||
auto function_state = detail::function_state::make<Function>(std::move(name), std::move(function));
|
||||
data_->functions.emplace(function_state->index, std::move(function_state));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < member_kind Member >
|
||||
class_bind<Class>& class_bind<Class>::member_(std::string name, Member member) {
|
||||
auto member_state = detail::member_state::make<Member>(std::move(name), std::move(member));
|
||||
data_->members.emplace(member_state->index, std::move(member_state));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < method_kind Method >
|
||||
class_bind<Class>& class_bind<Class>::method_(std::string name, Method method) {
|
||||
auto method_state = detail::method_state::make<Method>(std::move(name), std::move(method));
|
||||
data_->methods.emplace(method_state->index, std::move(method_state));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
template < pointer_kind Pointer >
|
||||
class_bind<Class>& class_bind<Class>::variable_(std::string name, Pointer pointer) {
|
||||
auto variable_state = detail::variable_state::make<Pointer>(std::move(name), std::move(pointer));
|
||||
data_->variables.emplace(variable_state->index, std::move(variable_state));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
29
headers/meta.hpp/meta_registry/enum_bind.hpp
Normal file
29
headers/meta.hpp/meta_registry/enum_bind.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_registry.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < enum_kind Enum >
|
||||
enum_bind<Enum>::enum_bind()
|
||||
: data_{detail::get_type_data<Enum>()} {}
|
||||
|
||||
template < enum_kind Enum >
|
||||
enum_bind<Enum>::operator enum_type() const noexcept {
|
||||
return enum_type{data_};
|
||||
}
|
||||
|
||||
template < enum_kind Enum >
|
||||
enum_bind<Enum>& enum_bind<Enum>::evalue_(std::string name, Enum value) {
|
||||
auto evalue_state = detail::evalue_state::make(std::move(name), std::move(value));
|
||||
data_->evalues.emplace(evalue_state->index, std::move(evalue_state));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
48
headers/meta.hpp/meta_registry/scope_bind.hpp
Normal file
48
headers/meta.hpp/meta_registry/scope_bind.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_registry.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline scope_bind::scope_bind(std::string_view name)
|
||||
: state_{detail::get_scope_state(name)} {}
|
||||
|
||||
inline scope_bind::operator scope() const noexcept {
|
||||
return scope{state_};
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
scope_bind& scope_bind::class_(std::string name) {
|
||||
auto class_data = detail::class_type_data::get<Class>();
|
||||
state_->classes.emplace(std::move(name), class_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < enum_kind Enum >
|
||||
scope_bind& scope_bind::enum_(std::string name) {
|
||||
auto enum_data = detail::enum_type_data::get<Enum>();
|
||||
state_->enums.emplace(std::move(name), enum_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
scope_bind& scope_bind::function_(std::string name, Function function) {
|
||||
auto function_state = detail::function_state::make<Function>(std::move(name), std::move(function));
|
||||
state_->functions.emplace(function_state->index, std::move(function_state));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
scope_bind& scope_bind::variable_(std::string name, Pointer pointer) {
|
||||
auto variable_state = detail::variable_state::make<Pointer>(std::move(name), std::move(pointer));
|
||||
state_->variables.emplace(variable_state->index, std::move(variable_state));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
329
headers/meta.hpp/meta_states.hpp
Normal file
329
headers/meta.hpp/meta_states.hpp
Normal file
@@ -0,0 +1,329 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "meta_base.hpp"
|
||||
#include "meta_types.hpp"
|
||||
#include "meta_utilities.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename T >
|
||||
concept states_family =
|
||||
std::same_as<T, ctor> ||
|
||||
std::same_as<T, evalue> ||
|
||||
std::same_as<T, function> ||
|
||||
std::same_as<T, member> ||
|
||||
std::same_as<T, method> ||
|
||||
std::same_as<T, scope> ||
|
||||
std::same_as<T, variable>;
|
||||
|
||||
template < states_family T, states_family U >
|
||||
bool operator<(const T& l, const U& r) noexcept {
|
||||
if ( !static_cast<bool>(r) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !static_cast<bool>(l) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return l.get_index() < r.get_index();
|
||||
}
|
||||
|
||||
template < states_family T, states_family U >
|
||||
bool operator==(const T& l, const U& r) noexcept {
|
||||
if ( static_cast<bool>(l) != static_cast<bool>(r) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !static_cast<bool>(l) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return l.get_index() == r.get_index();
|
||||
}
|
||||
|
||||
template < states_family T, states_family U >
|
||||
bool operator!=(const T& l, const U& r) noexcept {
|
||||
return !(l == r);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class ctor final {
|
||||
public:
|
||||
explicit ctor() = default;
|
||||
explicit ctor(detail::ctor_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const ctor_index& get_index() const noexcept;
|
||||
const ctor_type& get_type() const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
value invoke(Args&&... args) const;
|
||||
|
||||
template < typename... Args >
|
||||
bool is_invocable_with() const noexcept;
|
||||
private:
|
||||
detail::ctor_state_ptr state_;
|
||||
};
|
||||
|
||||
class evalue final {
|
||||
public:
|
||||
explicit evalue() = default;
|
||||
explicit evalue(detail::evalue_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const evalue_index& get_index() const noexcept;
|
||||
const enum_type& get_type() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
const value& get_value() const noexcept;
|
||||
private:
|
||||
detail::evalue_state_ptr state_;
|
||||
};
|
||||
|
||||
class function final {
|
||||
public:
|
||||
explicit function() = default;
|
||||
explicit function(detail::function_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const function_index& get_index() const noexcept;
|
||||
const function_type& get_type() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
std::optional<value> invoke(Args&&... args) const;
|
||||
|
||||
template < typename... Args >
|
||||
bool is_invocable_with() const noexcept;
|
||||
private:
|
||||
detail::function_state_ptr state_;
|
||||
};
|
||||
|
||||
class member final {
|
||||
public:
|
||||
explicit member() = default;
|
||||
explicit member(detail::member_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const member_index& get_index() const noexcept;
|
||||
const member_type& get_type() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
template < typename Instance >
|
||||
value get(Instance&& instance) const;
|
||||
|
||||
template < typename Instance, typename Value >
|
||||
void set(Instance&& instance, Value&& value) const;
|
||||
private:
|
||||
detail::member_state_ptr state_;
|
||||
};
|
||||
|
||||
class method final {
|
||||
public:
|
||||
explicit method() = default;
|
||||
explicit method(detail::method_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const method_index& get_index() const noexcept;
|
||||
const method_type& get_type() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
template < typename Instance, typename... Args >
|
||||
std::optional<value> invoke(Instance&& instance, Args&&... args) const;
|
||||
|
||||
template < typename Inst, typename... Args >
|
||||
bool is_invocable_with() const noexcept;
|
||||
private:
|
||||
detail::method_state_ptr state_;
|
||||
};
|
||||
|
||||
class scope final {
|
||||
public:
|
||||
explicit scope() = default;
|
||||
explicit scope(detail::scope_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const scope_index& get_index() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
const class_map& get_classes() const noexcept;
|
||||
const enum_map& get_enums() const noexcept;
|
||||
const function_map& get_functions() const noexcept;
|
||||
const variable_map& get_variables() const noexcept;
|
||||
|
||||
class_type get_class(std::string_view name) const noexcept;
|
||||
enum_type get_enum(std::string_view name) const noexcept;
|
||||
function get_function(std::string_view name) const noexcept;
|
||||
variable get_variable(std::string_view name) const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
function get_function_with(std::string_view name) const noexcept;
|
||||
function get_function_with(std::string_view name, std::vector<any_type> args) const noexcept;
|
||||
function get_function_with(std::string_view name, std::initializer_list<any_type> args) const noexcept;
|
||||
private:
|
||||
detail::scope_state_ptr state_;
|
||||
};
|
||||
|
||||
class variable final {
|
||||
public:
|
||||
explicit variable() = default;
|
||||
explicit variable(detail::variable_state_ptr state);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const variable_index& get_index() const noexcept;
|
||||
const pointer_type& get_type() const noexcept;
|
||||
const std::string& get_name() const noexcept;
|
||||
|
||||
value get() const;
|
||||
|
||||
template < typename Value >
|
||||
void set(Value&& value) const;
|
||||
private:
|
||||
detail::variable_state_ptr state_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
struct ctor_state final {
|
||||
using invoke_impl = std::function<value(const arg*, std::size_t)>;
|
||||
using is_invocable_with_impl = std::function<bool(const arg_base*, std::size_t)>;
|
||||
|
||||
ctor_index index;
|
||||
|
||||
invoke_impl invoke;
|
||||
is_invocable_with_impl is_invocable_with;
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
static ctor_state_ptr make();
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
explicit ctor_state(ctor_index index, type_list<Class>, type_list<Args...>);
|
||||
};
|
||||
|
||||
struct evalue_state final {
|
||||
evalue_index index;
|
||||
|
||||
class value value;
|
||||
|
||||
template < enum_kind Enum >
|
||||
static evalue_state_ptr make(std::string name, Enum value);
|
||||
|
||||
template < enum_kind Enum >
|
||||
explicit evalue_state(evalue_index index, Enum value);
|
||||
};
|
||||
|
||||
struct function_state final {
|
||||
using invoke_impl = std::function<std::optional<value>(const arg*, std::size_t)>;
|
||||
using is_invocable_with_impl = std::function<bool(const arg_base*, std::size_t)>;
|
||||
|
||||
function_index index;
|
||||
|
||||
invoke_impl invoke;
|
||||
is_invocable_with_impl is_invocable_with;
|
||||
|
||||
template < function_kind Function >
|
||||
static function_state_ptr make(std::string name, Function function);
|
||||
|
||||
template < function_kind Function >
|
||||
explicit function_state(function_index index, Function function);
|
||||
};
|
||||
|
||||
struct member_state final {
|
||||
using getter_impl = std::function<value(const inst&)>;
|
||||
using setter_impl = std::function<void(const inst&, const arg&)>;
|
||||
|
||||
member_index index;
|
||||
|
||||
getter_impl getter;
|
||||
setter_impl setter;
|
||||
|
||||
template < member_kind Member >
|
||||
static member_state_ptr make(std::string name, Member member);
|
||||
|
||||
template < member_kind Member >
|
||||
explicit member_state(member_index index, Member member);
|
||||
};
|
||||
|
||||
struct method_state final {
|
||||
using invoke_impl = std::function<std::optional<value>(const inst&, const arg*, std::size_t)>;
|
||||
using is_invocable_with_impl = std::function<bool(const inst_base&, const arg_base*, std::size_t)>;
|
||||
|
||||
method_index index;
|
||||
|
||||
invoke_impl invoke;
|
||||
is_invocable_with_impl is_invocable_with;
|
||||
|
||||
template < method_kind Method >
|
||||
static method_state_ptr make(std::string name, Method method);
|
||||
|
||||
template < method_kind Method >
|
||||
explicit method_state(method_index index, Method method);
|
||||
};
|
||||
|
||||
struct scope_state final {
|
||||
scope_index index;
|
||||
|
||||
class_map classes;
|
||||
enum_map enums;
|
||||
function_map functions;
|
||||
variable_map variables;
|
||||
|
||||
static scope_state_ptr get(std::string_view name);
|
||||
|
||||
explicit scope_state(scope_index index);
|
||||
};
|
||||
|
||||
struct variable_state final {
|
||||
using getter_impl = std::function<value()>;
|
||||
using setter_impl = std::function<void(const arg&)>;
|
||||
|
||||
variable_index index;
|
||||
|
||||
getter_impl getter;
|
||||
setter_impl setter;
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
static variable_state_ptr make(std::string name, Pointer pointer);
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
explicit variable_state(variable_index index, Pointer pointer);
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline scope_state_ptr get_scope_state(std::string_view name) {
|
||||
return scope_state::get(name);
|
||||
}
|
||||
}
|
||||
|
||||
inline scope resolve_scope(std::string_view name) {
|
||||
return scope{detail::get_scope_state(name)};
|
||||
}
|
||||
}
|
||||
146
headers/meta.hpp/meta_states/ctor.hpp
Normal file
146
headers/meta.hpp/meta_states/ctor.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/ctor_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class, typename... Args, std::size_t... Is >
|
||||
value raw_ctor_invoke_impl(
|
||||
const arg* args,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using ct = ctor_traits<Class, Args...>;
|
||||
using class_type = typename ct::class_type;
|
||||
using argument_types = typename ct::argument_types;
|
||||
|
||||
if ( !(... && (args + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
|
||||
throw std::logic_error("an attempt to call a constructor with an incorrect argument types");
|
||||
}
|
||||
|
||||
class_type return_value{(args + Is)->cast<type_list_at_t<Is, argument_types>>()...};
|
||||
return value{std::forward<class_type>(return_value)};
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
value raw_ctor_invoke(
|
||||
const arg* args,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using ct = ctor_traits<Class, Args...>;
|
||||
|
||||
if ( arg_count != ct::arity ) {
|
||||
throw std::logic_error("an attempt to call a constructor with an incorrect arity");
|
||||
}
|
||||
|
||||
return raw_ctor_invoke_impl<Class, Args...>(
|
||||
args,
|
||||
std::make_index_sequence<ct::arity>());
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_state::invoke_impl make_ctor_invoke() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_ctor_invoke<Class, Args...>, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class, typename... Args, std::size_t... Is >
|
||||
bool raw_ctor_is_invocable_with_impl(
|
||||
const arg_base* arg_bases,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using ct = ctor_traits<Class, Args...>;
|
||||
using argument_types = typename ct::argument_types;
|
||||
return (... && (arg_bases + Is)->can_cast_to<type_list_at_t<Is, argument_types>>() );
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
bool raw_ctor_is_invocable_with(
|
||||
const arg_base* arg_bases,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using ct = ctor_traits<Class, Args...>;
|
||||
|
||||
if ( arg_count != ct::arity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return raw_ctor_is_invocable_with_impl<Class, Args...>(
|
||||
arg_bases,
|
||||
std::make_index_sequence<ct::arity>());
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_state::is_invocable_with_impl make_ctor_is_invocable_with() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_ctor_is_invocable_with<Class, Args...>, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_state_ptr ctor_state::make() {
|
||||
ctor_index index{ctor_type_data::get<Class, Args...>()};
|
||||
return std::make_shared<ctor_state>(std::move(index), type_list<Class>{}, type_list<Args...>{});
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_state::ctor_state(ctor_index index, type_list<Class>, type_list<Args...>)
|
||||
: index{std::move(index)}
|
||||
, invoke{make_ctor_invoke<Class, Args...>()}
|
||||
, is_invocable_with{make_ctor_is_invocable_with<Class, Args...>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline ctor::ctor(detail::ctor_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool ctor::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline ctor::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const ctor_index& ctor::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const ctor_type& ctor::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
inline value ctor::invoke(Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg, sizeof...(Args)> vargs{detail::arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(vargs.data(), vargs.size());
|
||||
} else {
|
||||
return state_->invoke(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
inline bool ctor::is_invocable_with() const noexcept {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg_base, sizeof...(Args)> arg_bases{detail::arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(arg_bases.data(), arg_bases.size());
|
||||
} else {
|
||||
return state_->is_invocable_with(nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
headers/meta.hpp/meta_states/evalue.hpp
Normal file
56
headers/meta.hpp/meta_states/evalue.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/enum_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < enum_kind Enum >
|
||||
evalue_state_ptr evalue_state::make(std::string name, Enum value) {
|
||||
evalue_index index{enum_type_data::get<Enum>(), std::move(name)};
|
||||
return std::make_shared<evalue_state>(std::move(index), std::move(value));
|
||||
}
|
||||
|
||||
template < enum_kind Enum >
|
||||
evalue_state::evalue_state(evalue_index index, Enum value)
|
||||
: index{std::move(index)}
|
||||
, value{std::move(value)} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline evalue::evalue(detail::evalue_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool evalue::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline evalue::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const evalue_index& evalue::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const enum_type& evalue::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
inline const std::string& evalue::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
inline const value& evalue::get_value() const noexcept {
|
||||
return state_->value;
|
||||
}
|
||||
}
|
||||
160
headers/meta.hpp/meta_states/function.hpp
Normal file
160
headers/meta.hpp/meta_states/function.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/function_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < function_kind Function, std::size_t... Is >
|
||||
std::optional<value> raw_function_invoke_impl(
|
||||
Function function,
|
||||
const arg* args,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using ft = function_traits<Function>;
|
||||
using return_type = typename ft::return_type;
|
||||
using argument_types = typename ft::argument_types;
|
||||
|
||||
if ( !(... && (args + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
|
||||
throw std::logic_error("an attempt to call a function with an incorrect argument types");
|
||||
}
|
||||
|
||||
if constexpr ( std::is_void_v<return_type> ) {
|
||||
std::invoke(function,
|
||||
(args + Is)->cast<type_list_at_t<Is, argument_types>>()...);
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return_type return_value{std::invoke(function,
|
||||
(args + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
|
||||
return value{std::forward<return_type>(return_value)};
|
||||
}
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
std::optional<value> raw_function_invoke(
|
||||
Function function,
|
||||
const arg* args,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using ft = function_traits<Function>;
|
||||
|
||||
if ( arg_count != ft::arity ) {
|
||||
throw std::logic_error("an attempt to call a function with an incorrect arity");
|
||||
}
|
||||
|
||||
return raw_function_invoke_impl<Function>(
|
||||
function,
|
||||
args,
|
||||
std::make_index_sequence<ft::arity>());
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
function_state::invoke_impl make_function_invoke(Function function) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_function_invoke<Function>, function, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < function_kind Function, std::size_t... Is >
|
||||
bool raw_function_is_invocable_with_impl(
|
||||
const arg_base* arg_bases,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using ft = function_traits<Function>;
|
||||
using argument_types = typename ft::argument_types;
|
||||
return (... && (arg_bases + Is)->can_cast_to<type_list_at_t<Is, argument_types>>() );
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
bool raw_function_is_invocable_with(
|
||||
const arg_base* arg_bases,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using ft = function_traits<Function>;
|
||||
|
||||
if ( arg_count != ft::arity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return raw_function_is_invocable_with_impl<Function>(
|
||||
arg_bases,
|
||||
std::make_index_sequence<ft::arity>());
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
function_state::is_invocable_with_impl make_function_is_invocable_with() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_function_is_invocable_with<Function>, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < function_kind Function >
|
||||
function_state_ptr function_state::make(std::string name, Function function) {
|
||||
function_index index{function_type_data::get<Function>(), std::move(name)};
|
||||
return std::make_shared<function_state>(std::move(index), std::move(function));
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
function_state::function_state(function_index index, Function function)
|
||||
: index{std::move(index)}
|
||||
, invoke{make_function_invoke(function)}
|
||||
, is_invocable_with{make_function_is_invocable_with<Function>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline function::function(detail::function_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool function::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline function::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const function_index& function::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const function_type& function::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
inline const std::string& function::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
std::optional<value> function::invoke(Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg, sizeof...(Args)> vargs{detail::arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(vargs.data(), vargs.size());
|
||||
} else {
|
||||
return state_->invoke(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
bool function::is_invocable_with() const noexcept {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg_base, sizeof...(Args)> arg_bases{detail::arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(arg_bases.data(), arg_bases.size());
|
||||
} else {
|
||||
return state_->is_invocable_with(nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
124
headers/meta.hpp/meta_states/member.hpp
Normal file
124
headers/meta.hpp/meta_states/member.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/member_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
value raw_member_getter(Member member, const inst& inst) {
|
||||
using mt = member_traits<Member>;
|
||||
using class_type = typename mt::class_type;
|
||||
using value_type = typename mt::value_type;
|
||||
|
||||
using qualified_type = const class_type;
|
||||
|
||||
if ( !inst.can_cast_to<qualified_type>() ) {
|
||||
throw std::logic_error("an attempt to get a member with an incorrect instance type");
|
||||
}
|
||||
|
||||
value_type return_value{std::invoke(member, inst.cast<qualified_type>())};
|
||||
return value{std::forward<value_type>(return_value)};
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
void raw_member_setter([[maybe_unused]] Member member, const inst& inst, const arg& arg) {
|
||||
using mt = member_traits<Member>;
|
||||
using class_type = typename mt::class_type;
|
||||
using value_type = typename mt::value_type;
|
||||
|
||||
using qualified_type = class_type;
|
||||
|
||||
if constexpr ( !std::is_const_v<value_type> ) {
|
||||
if ( inst.is_const() ) {
|
||||
throw std::logic_error("an attempt to set a member with an const instance type");
|
||||
}
|
||||
|
||||
if ( !inst.can_cast_to<qualified_type>() ) {
|
||||
throw std::logic_error("an attempt to set a member with an incorrect instance type");
|
||||
}
|
||||
|
||||
if ( !arg.can_cast_to<value_type>() ) {
|
||||
throw std::logic_error("an attempt to set a member with an incorrect argument type");
|
||||
}
|
||||
|
||||
std::invoke(member, inst.cast<qualified_type>()) = arg.cast<value_type>();
|
||||
} else {
|
||||
throw std::logic_error("an attempt to set a constant member");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
member_state::getter_impl make_member_getter(Member member) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_member_getter<Member>, member, _1);
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
member_state::setter_impl make_member_setter(Member member) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_member_setter<Member>, member, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
member_state_ptr member_state::make(std::string name, Member member) {
|
||||
member_index index{member_type_data::get<Member>(), std::move(name)};
|
||||
return std::make_shared<member_state>(std::move(index), std::move(member));
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
member_state::member_state(member_index index, Member member)
|
||||
: index{std::move(index)}
|
||||
, getter{make_member_getter(member)}
|
||||
, setter{make_member_setter(member)} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline member::member(detail::member_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool member::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline member::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const member_index& member::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const member_type& member::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
inline const std::string& member::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
template < typename Instance >
|
||||
value member::get(Instance&& instance) const {
|
||||
return state_->getter(detail::inst{std::forward<Instance>(instance)});
|
||||
}
|
||||
|
||||
template < typename Instance, typename Value >
|
||||
void member::set(Instance&& instance, Value&& value) const {
|
||||
state_->setter(detail::inst{std::forward<Instance>(instance)}, detail::arg{std::forward<Value>(value)});
|
||||
}
|
||||
}
|
||||
176
headers/meta.hpp/meta_states/method.hpp
Normal file
176
headers/meta.hpp/meta_states/method.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/method_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < method_kind Method, std::size_t... Is >
|
||||
std::optional<value> raw_method_invoke_impl(
|
||||
Method method,
|
||||
const inst& inst,
|
||||
const arg* args,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using mt = method_traits<Method>;
|
||||
using return_type = typename mt::return_type;
|
||||
using qualified_type = typename mt::qualified_type;
|
||||
using argument_types = typename mt::argument_types;
|
||||
|
||||
if ( !inst.can_cast_to<qualified_type>() ) {
|
||||
throw std::logic_error("an attempt to call a method with an incorrect instance type");
|
||||
}
|
||||
|
||||
if ( !(... && (args + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
|
||||
throw std::logic_error("an attempt to call a method with an incorrect argument types");
|
||||
}
|
||||
|
||||
if constexpr ( std::is_void_v<return_type> ) {
|
||||
std::invoke(method,
|
||||
inst.cast<qualified_type>(),
|
||||
(args + Is)->cast<type_list_at_t<Is, argument_types>>()...);
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return_type return_value{std::invoke(method,
|
||||
inst.cast<qualified_type>(),
|
||||
(args + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
|
||||
return value{std::forward<return_type>(return_value)};
|
||||
}
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
std::optional<value> raw_method_invoke(
|
||||
Method method,
|
||||
const inst& inst,
|
||||
const arg* args,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using mt = method_traits<Method>;
|
||||
|
||||
if ( arg_count != mt::arity ) {
|
||||
throw std::logic_error("an attempt to call a method with an incorrect arity");
|
||||
}
|
||||
|
||||
return raw_method_invoke_impl<Method>(
|
||||
method,
|
||||
inst,
|
||||
args,
|
||||
std::make_index_sequence<mt::arity>());
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
method_state::invoke_impl make_method_invoke(Method method) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_method_invoke<Method>, method, _1, _2, _3);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < method_kind Method, std::size_t... Is >
|
||||
bool raw_method_is_invocable_with_impl(
|
||||
const inst_base& inst_base,
|
||||
const arg_base* arg_bases,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using mt = method_traits<Method>;
|
||||
using qualified_type = typename mt::qualified_type;
|
||||
using argument_types = typename mt::argument_types;
|
||||
|
||||
return inst_base.can_cast_to<qualified_type>()
|
||||
&& (... && (arg_bases + Is)->can_cast_to<type_list_at_t<Is, argument_types>>() );
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
bool raw_method_is_invocable_with(
|
||||
const inst_base& inst_base,
|
||||
const arg_base* arg_bases,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using mt = method_traits<Method>;
|
||||
|
||||
if ( arg_count != mt::arity ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return raw_method_is_invocable_with_impl<Method>(
|
||||
inst_base,
|
||||
arg_bases,
|
||||
std::make_index_sequence<mt::arity>());
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
method_state::is_invocable_with_impl make_method_is_invocable_with() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_method_is_invocable_with<Method>, _1, _2, _3);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < method_kind Method >
|
||||
method_state_ptr method_state::make(std::string name, Method method) {
|
||||
method_index index{method_type_data::get<Method>(), std::move(name)};
|
||||
return std::make_shared<method_state>(std::move(index), std::move(method));
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
method_state::method_state(method_index index, Method method)
|
||||
: index{std::move(index)}
|
||||
, invoke{make_method_invoke(method)}
|
||||
, is_invocable_with{make_method_is_invocable_with<Method>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline method::method(detail::method_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool method::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline method::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const method_index& method::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const method_type& method::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
inline const std::string& method::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
template < typename Instance, typename... Args >
|
||||
std::optional<value> method::invoke(Instance&& instance, Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg, sizeof...(Args)> vargs{detail::arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(detail::inst{std::forward<Instance>(instance)}, vargs.data(), vargs.size());
|
||||
} else {
|
||||
return state_->invoke(detail::inst{std::forward<Instance>(instance)}, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Inst, typename... Args >
|
||||
bool method::is_invocable_with() const noexcept {
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<detail::arg_base, sizeof...(Args)> arg_bases{detail::arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(detail::inst_base{type_list<Inst>{}}, arg_bases.data(), arg_bases.size());
|
||||
} else {
|
||||
return state_->is_invocable_with(detail::inst_base{type_list<Inst>{}}, nullptr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
headers/meta.hpp/meta_states/scope.hpp
Normal file
138
headers/meta.hpp/meta_states/scope.hpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
inline scope_state_ptr scope_state::get(std::string_view name) {
|
||||
static std::map<std::string, scope_state_ptr, std::less<>> states;
|
||||
|
||||
if ( auto iter = states.find(name); iter != states.end() ) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
auto state = std::make_shared<scope_state>(scope_index{std::string{name}});
|
||||
return states.emplace(std::string{name}, state).first->second;
|
||||
}
|
||||
|
||||
inline scope_state::scope_state(scope_index index)
|
||||
: index{std::move(index)} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline scope::scope(detail::scope_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool scope::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline scope::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const scope_index& scope::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const std::string& scope::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
inline const class_map& scope::get_classes() const noexcept {
|
||||
return state_->classes;
|
||||
}
|
||||
|
||||
inline const enum_map& scope::get_enums() const noexcept {
|
||||
return state_->enums;
|
||||
}
|
||||
|
||||
inline const function_map& scope::get_functions() const noexcept {
|
||||
return state_->functions;
|
||||
}
|
||||
|
||||
inline const variable_map& scope::get_variables() const noexcept {
|
||||
return state_->variables;
|
||||
}
|
||||
|
||||
inline class_type scope::get_class(std::string_view name) const noexcept {
|
||||
if ( auto iter = state_->classes.find(name); iter != state_->classes.end() ) {
|
||||
return iter->second;
|
||||
}
|
||||
return class_type{};
|
||||
}
|
||||
|
||||
inline enum_type scope::get_enum(std::string_view name) const noexcept {
|
||||
if ( auto iter = state_->enums.find(name); iter != state_->enums.end() ) {
|
||||
return iter->second;
|
||||
}
|
||||
return enum_type{};
|
||||
}
|
||||
|
||||
inline function scope::get_function(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, function] : state_->functions ) {
|
||||
if ( index.name == name ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
return function{};
|
||||
}
|
||||
|
||||
inline variable scope::get_variable(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, variable] : state_->variables ) {
|
||||
if ( index.name == name ) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
return variable{};
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
function scope::get_function_with(std::string_view name) const noexcept {
|
||||
return get_function_with(name, {resolve_type<Args>()...});
|
||||
}
|
||||
|
||||
inline function scope::get_function_with(std::string_view name, std::vector<any_type> args) const noexcept {
|
||||
for ( auto&& [index, function] : state_->functions ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( function.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& function_args = function.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), function_args.begin(), function_args.end()) ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
return function{};
|
||||
}
|
||||
|
||||
inline function scope::get_function_with(std::string_view name, std::initializer_list<any_type> args) const noexcept {
|
||||
for ( auto&& [index, function] : state_->functions ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( function.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& function_args = function.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), function_args.begin(), function_args.end()) ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
return function{};
|
||||
}
|
||||
}
|
||||
105
headers/meta.hpp/meta_states/variable.hpp
Normal file
105
headers/meta.hpp/meta_states/variable.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
|
||||
#include "../meta_types/pointer_type.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < pointer_kind Pointer >
|
||||
value raw_variable_getter(Pointer pointer) {
|
||||
using pt = pointer_traits<Pointer>;
|
||||
using data_type = typename pt::data_type;
|
||||
|
||||
data_type return_value{*pointer};
|
||||
return value{std::forward<data_type>(return_value)};
|
||||
}
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
void raw_variable_setter([[maybe_unused]] Pointer pointer, const arg& arg) {
|
||||
using pt = pointer_traits<Pointer>;
|
||||
using data_type = typename pt::data_type;
|
||||
|
||||
if constexpr ( !std::is_const_v<data_type> ) {
|
||||
if ( !arg.can_cast_to<data_type>() ) {
|
||||
throw std::logic_error("an attempt to set a variable with an incorrect argument type");
|
||||
}
|
||||
|
||||
*pointer = arg.cast<data_type>();
|
||||
} else {
|
||||
throw std::logic_error("an attempt to set a constant variable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < pointer_kind Pointer >
|
||||
variable_state::getter_impl make_variable_getter(Pointer pointer) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_variable_getter<Pointer>, pointer);
|
||||
}
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
variable_state::setter_impl make_variable_setter(Pointer pointer) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_variable_setter<Pointer>, pointer, _1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < pointer_kind Pointer >
|
||||
variable_state_ptr variable_state::make(std::string name, Pointer pointer) {
|
||||
variable_index index{pointer_type_data::get<Pointer>(), std::move(name)};
|
||||
return std::make_shared<variable_state>(index, pointer);
|
||||
}
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
variable_state::variable_state(variable_index index, Pointer pointer)
|
||||
: index{std::move(index)}
|
||||
, getter{make_variable_getter(pointer)}
|
||||
, setter{make_variable_setter(pointer)} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline variable::variable(detail::variable_state_ptr state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
inline bool variable::is_valid() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline variable::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline const variable_index& variable::get_index() const noexcept {
|
||||
return state_->index;
|
||||
}
|
||||
|
||||
inline const pointer_type& variable::get_type() const noexcept {
|
||||
return state_->index.type;
|
||||
}
|
||||
|
||||
inline const std::string& variable::get_name() const noexcept {
|
||||
return state_->index.name;
|
||||
}
|
||||
|
||||
inline value variable::get() const {
|
||||
return state_->getter();
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
void variable::set(Value&& value) const {
|
||||
state_->setter(detail::arg{std::forward<Value>(value)});
|
||||
}
|
||||
}
|
||||
722
headers/meta.hpp/meta_types.hpp
Normal file
722
headers/meta.hpp/meta_types.hpp
Normal file
@@ -0,0 +1,722 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "meta_base.hpp"
|
||||
#include "meta_traits.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class type_id final {
|
||||
public:
|
||||
template < typename T >
|
||||
explicit type_id(type_list<T>) noexcept
|
||||
: id_{type_to_id<T>()} {}
|
||||
|
||||
type_id(type_id&&) = default;
|
||||
type_id& operator=(type_id&&) = default;
|
||||
|
||||
type_id(const type_id&) = default;
|
||||
type_id& operator=(const type_id&) = default;
|
||||
|
||||
std::size_t get_hash() const noexcept {
|
||||
return std::hash<underlying_type>{}(id_);
|
||||
}
|
||||
|
||||
friend bool operator<(type_id l, type_id r) noexcept {
|
||||
return l.id_ < r.id_;
|
||||
}
|
||||
|
||||
friend bool operator==(type_id l, type_id r) noexcept {
|
||||
return l.id_ == r.id_;
|
||||
}
|
||||
|
||||
friend bool operator!=(type_id l, type_id r) noexcept {
|
||||
return l.id_ != r.id_;
|
||||
}
|
||||
private:
|
||||
using underlying_type = std::uint32_t;
|
||||
underlying_type id_{};
|
||||
private:
|
||||
static underlying_type next() noexcept {
|
||||
static std::atomic<underlying_type> id{};
|
||||
return ++id;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static underlying_type type_to_id() noexcept {
|
||||
static const underlying_type id{next()};
|
||||
return id;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename T >
|
||||
concept types_family =
|
||||
std::same_as<T, any_type> ||
|
||||
std::same_as<T, array_type> ||
|
||||
std::same_as<T, class_type> ||
|
||||
std::same_as<T, ctor_type> ||
|
||||
std::same_as<T, enum_type> ||
|
||||
std::same_as<T, function_type> ||
|
||||
std::same_as<T, member_type> ||
|
||||
std::same_as<T, method_type> ||
|
||||
std::same_as<T, number_type> ||
|
||||
std::same_as<T, pointer_type> ||
|
||||
std::same_as<T, reference_type> ||
|
||||
std::same_as<T, void_type>;
|
||||
|
||||
template < types_family T >
|
||||
bool operator<(type_id l, const T& r) noexcept {
|
||||
return static_cast<bool>(r) && l < r.get_id();
|
||||
}
|
||||
|
||||
template < types_family T >
|
||||
bool operator<(const T& l, type_id r) noexcept {
|
||||
return !static_cast<bool>(l) || l.get_id() < r;
|
||||
}
|
||||
|
||||
template < types_family T, types_family U >
|
||||
bool operator<(const T& l, const U& r) noexcept {
|
||||
if ( !static_cast<bool>(r) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !static_cast<bool>(l) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return l.get_id() < r.get_id();
|
||||
}
|
||||
|
||||
template < types_family T >
|
||||
bool operator==(type_id l, const T& r) noexcept {
|
||||
return static_cast<bool>(r) && l == r.get_id();
|
||||
}
|
||||
|
||||
template < types_family T >
|
||||
bool operator==(const T& l, type_id r) noexcept {
|
||||
return static_cast<bool>(l) && l.get_id() == r;
|
||||
}
|
||||
|
||||
template < types_family T, types_family U >
|
||||
bool operator==(const T& l, const U& r) noexcept {
|
||||
if ( static_cast<bool>(l) != static_cast<bool>(r) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !static_cast<bool>(l) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return l.get_id() == r.get_id();
|
||||
}
|
||||
|
||||
template < types_family T >
|
||||
bool operator!=(type_id l, const T& r) noexcept {
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
template < types_family T >
|
||||
bool operator!=(const T& l, type_id r) noexcept {
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
template < types_family T, types_family U >
|
||||
bool operator!=(const T& l, const U& r) noexcept {
|
||||
return !(l == r);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class any_type final {
|
||||
public:
|
||||
explicit any_type() = default;
|
||||
explicit any_type(detail::type_data_base_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
type_kind get_kind() const noexcept;
|
||||
|
||||
any_type(const array_type& other) noexcept;
|
||||
any_type(const class_type& other) noexcept;
|
||||
any_type(const ctor_type& other) noexcept;
|
||||
any_type(const enum_type& other) noexcept;
|
||||
any_type(const function_type& other) noexcept;
|
||||
any_type(const member_type& other) noexcept;
|
||||
any_type(const method_type& other) noexcept;
|
||||
any_type(const number_type& other) noexcept;
|
||||
any_type(const pointer_type& other) noexcept;
|
||||
any_type(const reference_type& other) noexcept;
|
||||
any_type(const void_type& other) noexcept;
|
||||
|
||||
bool is_array() const noexcept;
|
||||
bool is_class() const noexcept;
|
||||
bool is_ctor() const noexcept;
|
||||
bool is_enum() const noexcept;
|
||||
bool is_function() const noexcept;
|
||||
bool is_member() const noexcept;
|
||||
bool is_method() const noexcept;
|
||||
bool is_number() const noexcept;
|
||||
bool is_pointer() const noexcept;
|
||||
bool is_reference() const noexcept;
|
||||
bool is_void() const noexcept;
|
||||
|
||||
array_type as_array() const noexcept;
|
||||
class_type as_class() const noexcept;
|
||||
ctor_type as_ctor() const noexcept;
|
||||
enum_type as_enum() const noexcept;
|
||||
function_type as_function() const noexcept;
|
||||
member_type as_member() const noexcept;
|
||||
method_type as_method() const noexcept;
|
||||
number_type as_number() const noexcept;
|
||||
pointer_type as_pointer() const noexcept;
|
||||
reference_type as_reference() const noexcept;
|
||||
void_type as_void() const noexcept;
|
||||
private:
|
||||
detail::type_data_base_ptr data_;
|
||||
};
|
||||
|
||||
class array_type final {
|
||||
public:
|
||||
array_type() = default;
|
||||
array_type(detail::array_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<array_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_extent() const noexcept;
|
||||
any_type get_data_type() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::array_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class class_type final {
|
||||
public:
|
||||
class_type() = default;
|
||||
class_type(detail::class_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<class_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_size() const noexcept;
|
||||
|
||||
std::size_t get_arity() const noexcept;
|
||||
any_type get_argument_type(std::size_t index) const noexcept;
|
||||
const std::vector<any_type>& get_argument_types() const noexcept;
|
||||
|
||||
const ctor_map& get_ctors() const noexcept;
|
||||
const class_set& get_bases() const noexcept;
|
||||
const function_map& get_functions() const noexcept;
|
||||
const member_map& get_members() const noexcept;
|
||||
const method_map& get_methods() const noexcept;
|
||||
const variable_map& get_variables() const noexcept;
|
||||
|
||||
template < class_kind Derived >
|
||||
bool is_base_of() const noexcept;
|
||||
bool is_base_of(const class_type& derived) const noexcept;
|
||||
|
||||
template < class_kind Base >
|
||||
bool is_derived_from() const noexcept;
|
||||
bool is_derived_from(const class_type& base) const noexcept;
|
||||
|
||||
function get_function(std::string_view name) const noexcept;
|
||||
member get_member(std::string_view name) const noexcept;
|
||||
method get_method(std::string_view name) const noexcept;
|
||||
variable get_variable(std::string_view name) const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
ctor get_ctor_with() const noexcept;
|
||||
ctor get_ctor_with(std::vector<any_type> args) const noexcept;
|
||||
ctor get_ctor_with(std::initializer_list<any_type> args) const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
function get_function_with(std::string_view name) const noexcept;
|
||||
function get_function_with(std::string_view name, std::vector<any_type> args) const noexcept;
|
||||
function get_function_with(std::string_view name, std::initializer_list<any_type> args) const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
method get_method_with(std::string_view name) const noexcept;
|
||||
method get_method_with(std::string_view name, std::vector<any_type> args) const noexcept;
|
||||
method get_method_with(std::string_view name, std::initializer_list<any_type> args) const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::class_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class ctor_type final {
|
||||
public:
|
||||
ctor_type() = default;
|
||||
ctor_type(detail::ctor_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<ctor_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_arity() const noexcept;
|
||||
any_type get_class_type() const noexcept;
|
||||
any_type get_argument_type(std::size_t index) const noexcept;
|
||||
const std::vector<any_type>& get_argument_types() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::ctor_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class enum_type final {
|
||||
public:
|
||||
enum_type() = default;
|
||||
enum_type(detail::enum_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<enum_flags> get_flags() const noexcept;
|
||||
|
||||
number_type get_underlying_type() const noexcept;
|
||||
|
||||
const evalue_map& get_evalues() const noexcept;
|
||||
|
||||
evalue get_evalue(std::string_view name) const noexcept;
|
||||
|
||||
template < typename Value >
|
||||
std::optional<std::string> value_to_name(Value&& value) const noexcept;
|
||||
std::optional<value> name_to_value(std::string_view name) const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::enum_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class function_type final {
|
||||
public:
|
||||
function_type() = default;
|
||||
function_type(detail::function_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<function_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_arity() const noexcept;
|
||||
any_type get_return_type() const noexcept;
|
||||
any_type get_argument_type(std::size_t index) const noexcept;
|
||||
const std::vector<any_type>& get_argument_types() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::function_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class member_type final {
|
||||
public:
|
||||
member_type() = default;
|
||||
member_type(detail::member_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<member_flags> get_flags() const noexcept;
|
||||
|
||||
class_type get_owner_type() const noexcept;
|
||||
any_type get_value_type() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::member_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class method_type final {
|
||||
public:
|
||||
method_type() = default;
|
||||
method_type(detail::method_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<method_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_arity() const noexcept;
|
||||
class_type get_owner_type() const noexcept;
|
||||
any_type get_return_type() const noexcept;
|
||||
any_type get_argument_type(std::size_t index) const noexcept;
|
||||
const std::vector<any_type>& get_argument_types() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::method_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class number_type final {
|
||||
public:
|
||||
number_type() = default;
|
||||
number_type(detail::number_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<number_flags> get_flags() const noexcept;
|
||||
|
||||
std::size_t get_size() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::number_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class pointer_type final {
|
||||
public:
|
||||
pointer_type() = default;
|
||||
pointer_type(detail::pointer_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<pointer_flags> get_flags() const noexcept;
|
||||
|
||||
any_type get_data_type() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::pointer_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class reference_type final {
|
||||
public:
|
||||
reference_type() = default;
|
||||
reference_type(detail::reference_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<reference_flags> get_flags() const noexcept;
|
||||
|
||||
any_type get_data_type() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::reference_type_data_ptr data_;
|
||||
};
|
||||
|
||||
class void_type final {
|
||||
public:
|
||||
void_type() = default;
|
||||
void_type(detail::void_type_data_ptr data);
|
||||
|
||||
bool is_valid() const noexcept;
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
type_id get_id() const noexcept;
|
||||
bitflags<void_flags> get_flags() const noexcept;
|
||||
private:
|
||||
friend class any_type;
|
||||
detail::void_type_data_ptr data_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
struct type_data_base {
|
||||
const type_id id;
|
||||
const type_kind kind;
|
||||
|
||||
explicit type_data_base(type_id id, type_kind kind)
|
||||
: id{id}
|
||||
, kind{kind} {}
|
||||
};
|
||||
|
||||
struct array_type_data final : type_data_base {
|
||||
const bitflags<array_flags> flags;
|
||||
const std::size_t extent;
|
||||
const any_type data_type;
|
||||
|
||||
template < array_kind Array >
|
||||
static array_type_data_ptr get();
|
||||
|
||||
template < array_kind Array >
|
||||
explicit array_type_data(type_list<Array>);
|
||||
};
|
||||
|
||||
struct class_type_data final : type_data_base {
|
||||
const bitflags<class_flags> flags;
|
||||
const std::size_t size;
|
||||
const std::vector<any_type> argument_types;
|
||||
|
||||
ctor_map ctors;
|
||||
class_set bases;
|
||||
function_map functions;
|
||||
member_map members;
|
||||
method_map methods;
|
||||
variable_map variables;
|
||||
|
||||
template < class_kind Class >
|
||||
static class_type_data_ptr get();
|
||||
|
||||
template < class_kind Class >
|
||||
explicit class_type_data(type_list<Class>);
|
||||
};
|
||||
|
||||
struct ctor_type_data final : type_data_base {
|
||||
const bitflags<ctor_flags> flags;
|
||||
const any_type class_type;
|
||||
const std::vector<any_type> argument_types;
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
static ctor_type_data_ptr get();
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
explicit ctor_type_data(type_list<Class>, type_list<Args...>);
|
||||
};
|
||||
|
||||
struct enum_type_data final : type_data_base {
|
||||
const bitflags<enum_flags> flags;
|
||||
const number_type underlying_type;
|
||||
|
||||
evalue_map evalues;
|
||||
|
||||
template < enum_kind Enum >
|
||||
static enum_type_data_ptr get();
|
||||
|
||||
template < enum_kind Enum >
|
||||
explicit enum_type_data(type_list<Enum>);
|
||||
};
|
||||
|
||||
struct function_type_data final : type_data_base {
|
||||
const bitflags<function_flags> flags;
|
||||
const any_type return_type;
|
||||
const std::vector<any_type> argument_types;
|
||||
|
||||
template < function_kind Function >
|
||||
static function_type_data_ptr get();
|
||||
|
||||
template < function_kind Function >
|
||||
explicit function_type_data(type_list<Function>);
|
||||
};
|
||||
|
||||
struct member_type_data final : type_data_base {
|
||||
const bitflags<member_flags> flags;
|
||||
const class_type owner_type;
|
||||
const any_type value_type;
|
||||
|
||||
template < member_kind Member >
|
||||
static member_type_data_ptr get();
|
||||
|
||||
template < member_kind Member >
|
||||
explicit member_type_data(type_list<Member>);
|
||||
};
|
||||
|
||||
struct method_type_data final : type_data_base {
|
||||
const bitflags<method_flags> flags;
|
||||
const class_type owner_type;
|
||||
const any_type return_type;
|
||||
const std::vector<any_type> argument_types;
|
||||
|
||||
template < method_kind Method >
|
||||
static method_type_data_ptr get();
|
||||
|
||||
template < method_kind Method >
|
||||
explicit method_type_data(type_list<Method>);
|
||||
};
|
||||
|
||||
struct number_type_data final : type_data_base {
|
||||
const bitflags<number_flags> flags;
|
||||
const std::size_t size;
|
||||
|
||||
template < number_kind Number >
|
||||
static number_type_data_ptr get();
|
||||
|
||||
template < number_kind Number >
|
||||
explicit number_type_data(type_list<Number>);
|
||||
};
|
||||
|
||||
struct pointer_type_data final : type_data_base {
|
||||
const bitflags<pointer_flags> flags;
|
||||
const any_type data_type;
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
static pointer_type_data_ptr get();
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
explicit pointer_type_data(type_list<Pointer>);
|
||||
};
|
||||
|
||||
struct reference_type_data final : type_data_base {
|
||||
const bitflags<reference_flags> flags;
|
||||
const any_type data_type;
|
||||
|
||||
template < reference_kind Reference >
|
||||
static reference_type_data_ptr get();
|
||||
|
||||
template < reference_kind Reference >
|
||||
explicit reference_type_data(type_list<Reference>);
|
||||
};
|
||||
|
||||
struct void_type_data final : type_data_base {
|
||||
const bitflags<void_flags> flags;
|
||||
|
||||
template < void_kind Void >
|
||||
static void_type_data_ptr get();
|
||||
|
||||
template < void_kind Void >
|
||||
explicit void_type_data(type_list<Void>);
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
struct ctor_index final {
|
||||
const ctor_type type;
|
||||
|
||||
explicit ctor_index(ctor_type type)
|
||||
: type{std::move(type)} {}
|
||||
|
||||
friend bool operator<(const ctor_index& l, const ctor_index& r) noexcept {
|
||||
return l.type < r.type;
|
||||
}
|
||||
|
||||
friend bool operator==(const ctor_index& l, const ctor_index& r) noexcept {
|
||||
return l.type == r.type;
|
||||
}
|
||||
};
|
||||
|
||||
struct evalue_index final {
|
||||
const enum_type type;
|
||||
const std::string name;
|
||||
|
||||
explicit evalue_index(enum_type type, std::string name)
|
||||
: type{std::move(type)}
|
||||
, name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const evalue_index& l, const evalue_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) < std::tie(r.type, r.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const evalue_index& l, const evalue_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) == std::tie(r.type, r.name);
|
||||
}
|
||||
};
|
||||
|
||||
struct function_index final {
|
||||
const function_type type;
|
||||
const std::string name;
|
||||
|
||||
explicit function_index(function_type type, std::string name)
|
||||
: type{std::move(type)}
|
||||
, name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const function_index& l, const function_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) < std::tie(r.type, r.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const function_index& l, const function_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) == std::tie(r.type, r.name);
|
||||
}
|
||||
};
|
||||
|
||||
struct member_index final {
|
||||
const member_type type;
|
||||
const std::string name;
|
||||
|
||||
explicit member_index(member_type type, std::string name)
|
||||
: type{std::move(type)}
|
||||
, name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const member_index& l, const member_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) < std::tie(r.type, r.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const member_index& l, const member_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) == std::tie(r.type, r.name);
|
||||
}
|
||||
};
|
||||
|
||||
struct method_index final {
|
||||
const method_type type;
|
||||
const std::string name;
|
||||
|
||||
explicit method_index(method_type type, std::string name)
|
||||
: type{std::move(type)}
|
||||
, name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const method_index& l, const method_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) < std::tie(r.type, r.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const method_index& l, const method_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) == std::tie(r.type, r.name);
|
||||
}
|
||||
};
|
||||
|
||||
struct scope_index final {
|
||||
const std::string name;
|
||||
|
||||
explicit scope_index(std::string name)
|
||||
: name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const scope_index& l, const scope_index& r) noexcept {
|
||||
return l.name < r.name;
|
||||
}
|
||||
|
||||
friend bool operator==(const scope_index& l, const scope_index& r) noexcept {
|
||||
return l.name == r.name;
|
||||
}
|
||||
};
|
||||
|
||||
struct variable_index final {
|
||||
const pointer_type type;
|
||||
const std::string name;
|
||||
|
||||
explicit variable_index(pointer_type type, std::string name)
|
||||
: type{std::move(type)}
|
||||
, name{std::move(name)} {}
|
||||
|
||||
friend bool operator<(const variable_index& l, const variable_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) < std::tie(r.type, r.name);
|
||||
}
|
||||
|
||||
friend bool operator==(const variable_index& l, const variable_index& r) noexcept {
|
||||
return std::tie(l.type, l.name) == std::tie(r.type, r.name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template < typename T >
|
||||
kind_type_data_ptr<T> get_type_data() {
|
||||
static_assert(!std::is_const_v<T> && !std::is_volatile_v<T>);
|
||||
return kind_type_data<T>::template get<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
auto resolve_type() {
|
||||
using raw_type = std::remove_cv_t<T>;
|
||||
return detail::kind_type<raw_type>{detail::get_type_data<raw_type>()};
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
auto resolve_type(T&&) {
|
||||
using raw_type = std::remove_cvref_t<T>;
|
||||
return detail::kind_type<raw_type>{detail::get_type_data<raw_type>()};
|
||||
};
|
||||
}
|
||||
169
headers/meta.hpp/meta_types/any_type.hpp
Normal file
169
headers/meta.hpp/meta_types/any_type.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline any_type::any_type(detail::type_data_base_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool any_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline any_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id any_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline type_kind any_type::get_kind() const noexcept {
|
||||
return data_->kind;
|
||||
}
|
||||
|
||||
inline any_type::any_type(const array_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const class_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const ctor_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const enum_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const function_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const member_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const method_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const number_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const pointer_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const reference_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline any_type::any_type(const void_type& other) noexcept
|
||||
: data_{other.data_} {}
|
||||
|
||||
inline bool any_type::is_array() const noexcept {
|
||||
return data_ && data_->kind == type_kind::array_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_class() const noexcept {
|
||||
return data_ && data_->kind == type_kind::class_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_ctor() const noexcept {
|
||||
return data_ && data_->kind == type_kind::ctor_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_enum() const noexcept {
|
||||
return data_ && data_->kind == type_kind::enum_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_function() const noexcept {
|
||||
return data_ && data_->kind == type_kind::function_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_member() const noexcept {
|
||||
return data_ && data_->kind == type_kind::member_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_method() const noexcept {
|
||||
return data_ && data_->kind == type_kind::method_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_number() const noexcept {
|
||||
return data_ && data_->kind == type_kind::number_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_pointer() const noexcept {
|
||||
return data_ && data_->kind == type_kind::pointer_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_reference() const noexcept {
|
||||
return data_ && data_->kind == type_kind::reference_;
|
||||
}
|
||||
|
||||
inline bool any_type::is_void() const noexcept {
|
||||
return data_ && data_->kind == type_kind::void_;
|
||||
}
|
||||
|
||||
inline array_type any_type::as_array() const noexcept {
|
||||
return is_array()
|
||||
? array_type{std::static_pointer_cast<detail::array_type_data>(data_)}
|
||||
: array_type{};
|
||||
}
|
||||
|
||||
inline class_type any_type::as_class() const noexcept {
|
||||
return is_class()
|
||||
? class_type{std::static_pointer_cast<detail::class_type_data>(data_)}
|
||||
: class_type{};
|
||||
}
|
||||
|
||||
inline enum_type any_type::as_enum() const noexcept {
|
||||
return is_enum()
|
||||
? enum_type{std::static_pointer_cast<detail::enum_type_data>(data_)}
|
||||
: enum_type{};
|
||||
}
|
||||
|
||||
inline function_type any_type::as_function() const noexcept {
|
||||
return is_function()
|
||||
? function_type{std::static_pointer_cast<detail::function_type_data>(data_)}
|
||||
: function_type{};
|
||||
}
|
||||
|
||||
inline member_type any_type::as_member() const noexcept {
|
||||
return is_member()
|
||||
? member_type{std::static_pointer_cast<detail::member_type_data>(data_)}
|
||||
: member_type{};
|
||||
}
|
||||
|
||||
inline method_type any_type::as_method() const noexcept {
|
||||
return is_method()
|
||||
? method_type{std::static_pointer_cast<detail::method_type_data>(data_)}
|
||||
: method_type{};
|
||||
}
|
||||
|
||||
inline number_type any_type::as_number() const noexcept {
|
||||
return is_number()
|
||||
? number_type{std::static_pointer_cast<detail::number_type_data>(data_)}
|
||||
: number_type{};
|
||||
}
|
||||
|
||||
inline pointer_type any_type::as_pointer() const noexcept {
|
||||
return is_pointer()
|
||||
? pointer_type{std::static_pointer_cast<detail::pointer_type_data>(data_)}
|
||||
: pointer_type{};
|
||||
}
|
||||
|
||||
inline reference_type any_type::as_reference() const noexcept {
|
||||
return is_reference()
|
||||
? reference_type{std::static_pointer_cast<detail::reference_type_data>(data_)}
|
||||
: reference_type{};
|
||||
}
|
||||
|
||||
inline void_type any_type::as_void() const noexcept {
|
||||
return is_void()
|
||||
? void_type{std::static_pointer_cast<detail::void_type_data>(data_)}
|
||||
: void_type{};
|
||||
}
|
||||
}
|
||||
61
headers/meta.hpp/meta_types/array_type.hpp
Normal file
61
headers/meta.hpp/meta_types/array_type.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/array_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < array_kind Array >
|
||||
struct array_tag {};
|
||||
|
||||
template < array_kind Array >
|
||||
array_type_data_ptr array_type_data::get() {
|
||||
static array_type_data_ptr data = std::make_shared<array_type_data>(type_list<Array>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < array_kind Array >
|
||||
array_type_data::array_type_data(type_list<Array>)
|
||||
: type_data_base{type_id{type_list<array_tag<Array>>{}}, type_kind::array_}
|
||||
, flags{array_traits<Array>::make_flags()}
|
||||
, extent{array_traits<Array>::extent}
|
||||
, data_type{resolve_type<typename array_traits<Array>::data_type>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline array_type::array_type(detail::array_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool array_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline array_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id array_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<array_flags> array_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t array_type::get_extent() const noexcept {
|
||||
return data_->extent;
|
||||
}
|
||||
|
||||
inline any_type array_type::get_data_type() const noexcept {
|
||||
return data_->data_type;
|
||||
}
|
||||
}
|
||||
332
headers/meta.hpp/meta_types/class_type.hpp
Normal file
332
headers/meta.hpp/meta_types/class_type.hpp
Normal file
@@ -0,0 +1,332 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/class_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class >
|
||||
struct class_tag {};
|
||||
|
||||
template < class_kind Class >
|
||||
class_type_data_ptr class_type_data::get() {
|
||||
static class_type_data_ptr data = std::make_shared<class_type_data>(type_list<Class>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < class_kind Class >
|
||||
class_type_data::class_type_data(type_list<Class>)
|
||||
: type_data_base{type_id{type_list<class_tag<Class>>{}}, type_kind::class_}
|
||||
, flags{class_traits<Class>::make_flags()}
|
||||
, size{class_traits<Class>::size}
|
||||
, argument_types{class_traits<Class>::make_argument_types()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline class_type::class_type(detail::class_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool class_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline class_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id class_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<class_flags> class_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t class_type::get_size() const noexcept {
|
||||
return data_->size;
|
||||
}
|
||||
|
||||
inline std::size_t class_type::get_arity() const noexcept {
|
||||
return data_->argument_types.size();
|
||||
}
|
||||
|
||||
inline any_type class_type::get_argument_type(std::size_t index) const noexcept {
|
||||
return index < data_->argument_types.size() ? data_->argument_types[index] : any_type{};
|
||||
}
|
||||
|
||||
inline const std::vector<any_type>& class_type::get_argument_types() const noexcept {
|
||||
return data_->argument_types;
|
||||
}
|
||||
|
||||
inline const ctor_map& class_type::get_ctors() const noexcept {
|
||||
return data_->ctors;
|
||||
}
|
||||
|
||||
inline const class_set& class_type::get_bases() const noexcept {
|
||||
return data_->bases;
|
||||
}
|
||||
|
||||
inline const function_map& class_type::get_functions() const noexcept {
|
||||
return data_->functions;
|
||||
}
|
||||
|
||||
inline const member_map& class_type::get_members() const noexcept {
|
||||
return data_->members;
|
||||
}
|
||||
|
||||
inline const method_map& class_type::get_methods() const noexcept {
|
||||
return data_->methods;
|
||||
}
|
||||
|
||||
inline const variable_map& class_type::get_variables() const noexcept {
|
||||
return data_->variables;
|
||||
}
|
||||
|
||||
template < class_kind Derived >
|
||||
bool class_type::is_base_of() const noexcept {
|
||||
return is_base_of(resolve_type<Derived>());
|
||||
}
|
||||
|
||||
inline bool class_type::is_base_of(const class_type& derived) const noexcept {
|
||||
return derived.data_ && derived.data_->bases.contains(*this);
|
||||
}
|
||||
|
||||
template < class_kind Base >
|
||||
bool class_type::is_derived_from() const noexcept {
|
||||
return is_derived_from(resolve_type<Base>());
|
||||
}
|
||||
|
||||
inline bool class_type::is_derived_from(const class_type& base) const noexcept {
|
||||
return data_ && data_->bases.contains(base);
|
||||
}
|
||||
|
||||
inline function class_type::get_function(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, function] : data_->functions ) {
|
||||
if ( index.name == name ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( function function = base.get_function(name); function ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
return function{};
|
||||
}
|
||||
|
||||
inline member class_type::get_member(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, member] : data_->members ) {
|
||||
if ( index.name == name ) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( member member = base.get_member(name); member ) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
return member{};
|
||||
}
|
||||
|
||||
inline method class_type::get_method(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, method] : data_->methods ) {
|
||||
if ( index.name == name ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( method method = base.get_method(name); method ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
return method{};
|
||||
}
|
||||
|
||||
inline variable class_type::get_variable(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, variable] : data_->variables ) {
|
||||
if ( index.name == name ) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( variable variable = base.get_variable(name); variable ) {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
return variable{};
|
||||
}
|
||||
|
||||
//
|
||||
// get_ctor_with
|
||||
//
|
||||
|
||||
template < typename... Args >
|
||||
ctor class_type::get_ctor_with() const noexcept {
|
||||
return get_ctor_with({resolve_type<Args>()...});
|
||||
}
|
||||
|
||||
inline ctor class_type::get_ctor_with(std::vector<any_type> args) const noexcept {
|
||||
for ( auto&& [index, ctor] : data_->ctors ) {
|
||||
if ( ctor.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& ctor_args = ctor.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), ctor_args.begin(), ctor_args.end()) ) {
|
||||
return ctor;
|
||||
}
|
||||
}
|
||||
|
||||
return ctor{};
|
||||
}
|
||||
|
||||
inline ctor class_type::get_ctor_with(std::initializer_list<any_type> args) const noexcept {
|
||||
for ( auto&& [index, ctor] : data_->ctors ) {
|
||||
if ( ctor.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& ctor_args = ctor.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), ctor_args.begin(), ctor_args.end()) ) {
|
||||
return ctor;
|
||||
}
|
||||
}
|
||||
|
||||
return ctor{};
|
||||
}
|
||||
|
||||
//
|
||||
// get_function_with
|
||||
//
|
||||
|
||||
template < typename... Args >
|
||||
function class_type::get_function_with(std::string_view name) const noexcept {
|
||||
return get_function_with(name, {resolve_type<Args>()...});
|
||||
}
|
||||
|
||||
inline function class_type::get_function_with(std::string_view name, std::vector<any_type> args) const noexcept {
|
||||
for ( auto&& [index, function] : data_->functions ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( function.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& function_args = function.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), function_args.begin(), function_args.end()) ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( function function = base.get_function_with(name, args); function ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
return function{};
|
||||
}
|
||||
|
||||
inline function class_type::get_function_with(std::string_view name, std::initializer_list<any_type> args) const noexcept {
|
||||
for ( auto&& [index, function] : data_->functions ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( function.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& function_args = function.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), function_args.begin(), function_args.end()) ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( function function = base.get_function_with(name, args); function ) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
return function{};
|
||||
}
|
||||
|
||||
//
|
||||
// get_method_with
|
||||
//
|
||||
|
||||
template < typename... Args >
|
||||
method class_type::get_method_with(std::string_view name) const noexcept {
|
||||
return get_method_with(name, {resolve_type<Args>()...});
|
||||
}
|
||||
|
||||
inline method class_type::get_method_with(std::string_view name, std::vector<any_type> args) const noexcept {
|
||||
for ( auto&& [index, method] : data_->methods ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( method.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& method_args = method.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), method_args.begin(), method_args.end()) ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( method method = base.get_method_with(name, args); method ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
return method{};
|
||||
}
|
||||
|
||||
inline method class_type::get_method_with(std::string_view name, std::initializer_list<any_type> args) const noexcept {
|
||||
for ( auto&& [index, method] : data_->methods ) {
|
||||
if ( index.name != name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( method.get_type().get_arity() != args.size() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<any_type>& method_args = method.get_type().get_argument_types();
|
||||
if ( std::equal(args.begin(), args.end(), method_args.begin(), method_args.end()) ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto&& base : data_->bases ) {
|
||||
if ( method method = base.get_method_with(name, args); method ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
return method{};
|
||||
}
|
||||
}
|
||||
69
headers/meta.hpp/meta_types/ctor_type.hpp
Normal file
69
headers/meta.hpp/meta_types/ctor_type.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/ctor_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class, typename... Args >
|
||||
struct ctor_tag {};
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_type_data_ptr ctor_type_data::get() {
|
||||
static ctor_type_data_ptr data = std::make_shared<ctor_type_data>(type_list<Class>{}, type_list<Args...>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_type_data::ctor_type_data(type_list<Class>, type_list<Args...>)
|
||||
: type_data_base{type_id{type_list<ctor_tag<Class, Args...>>{}}, type_kind::ctor_}
|
||||
, flags{ctor_traits<Class, Args...>::make_flags()}
|
||||
, class_type{resolve_type<typename ctor_traits<Class, Args...>::class_type>()}
|
||||
, argument_types{ctor_traits<Class, Args...>::make_argument_types()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline ctor_type::ctor_type(detail::ctor_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool ctor_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline ctor_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id ctor_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<ctor_flags> ctor_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t ctor_type::get_arity() const noexcept {
|
||||
return data_->argument_types.size();
|
||||
}
|
||||
|
||||
inline any_type ctor_type::get_class_type() const noexcept {
|
||||
return data_->class_type;
|
||||
}
|
||||
|
||||
inline any_type ctor_type::get_argument_type(std::size_t index) const noexcept {
|
||||
return index < data_->argument_types.size() ? data_->argument_types[index] : any_type{};
|
||||
}
|
||||
|
||||
inline const std::vector<any_type>& ctor_type::get_argument_types() const noexcept {
|
||||
return data_->argument_types;
|
||||
}
|
||||
}
|
||||
93
headers/meta.hpp/meta_types/enum_type.hpp
Normal file
93
headers/meta.hpp/meta_types/enum_type.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/enum_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < enum_kind Enum >
|
||||
struct enum_tag {};
|
||||
|
||||
template < enum_kind Enum >
|
||||
enum_type_data_ptr enum_type_data::get() {
|
||||
static enum_type_data_ptr data = std::make_shared<enum_type_data>(type_list<Enum>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < enum_kind Enum >
|
||||
enum_type_data::enum_type_data(type_list<Enum>)
|
||||
: type_data_base{type_id{type_list<enum_tag<Enum>>{}}, type_kind::enum_}
|
||||
, flags{enum_traits<Enum>::make_flags()}
|
||||
, underlying_type{resolve_type<typename enum_traits<Enum>::underlying_type>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline enum_type::enum_type(detail::enum_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool enum_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline enum_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id enum_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<enum_flags> enum_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline number_type enum_type::get_underlying_type() const noexcept {
|
||||
return data_->underlying_type;
|
||||
}
|
||||
|
||||
inline const evalue_map& enum_type::get_evalues() const noexcept {
|
||||
return data_->evalues;
|
||||
}
|
||||
|
||||
inline evalue enum_type::get_evalue(std::string_view name) const noexcept {
|
||||
for ( auto&& [index, evalue] : data_->evalues ) {
|
||||
if ( index.name == name ) {
|
||||
return evalue;
|
||||
}
|
||||
}
|
||||
return evalue{};
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
std::optional<std::string> enum_type::value_to_name(Value&& value) const noexcept {
|
||||
const detail::arg value_arg{std::forward<Value>(value)};
|
||||
|
||||
if ( value_arg.get_raw_type() != *this ) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
for ( auto&& evalue : data_->evalues ) {
|
||||
if ( evalue.second.get_value() == value ) {
|
||||
return evalue.second.get_index().name;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline std::optional<value> enum_type::name_to_value(std::string_view name) const noexcept {
|
||||
if ( const evalue value = get_evalue(name); value ) {
|
||||
return value.get_value();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
69
headers/meta.hpp/meta_types/function_type.hpp
Normal file
69
headers/meta.hpp/meta_types/function_type.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/function_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < function_kind Function >
|
||||
struct function_tag {};
|
||||
|
||||
template < function_kind Function >
|
||||
function_type_data_ptr function_type_data::get() {
|
||||
static function_type_data_ptr data = std::make_shared<function_type_data>(type_list<Function>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
function_type_data::function_type_data(type_list<Function>)
|
||||
: type_data_base{type_id{type_list<function_tag<Function>>{}}, type_kind::function_}
|
||||
, flags{function_traits<Function>::make_flags()}
|
||||
, return_type{resolve_type<typename function_traits<Function>::return_type>()}
|
||||
, argument_types{function_traits<Function>::make_argument_types()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline function_type::function_type(detail::function_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool function_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline function_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id function_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<function_flags> function_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t function_type::get_arity() const noexcept {
|
||||
return data_->argument_types.size();
|
||||
}
|
||||
|
||||
inline any_type function_type::get_return_type() const noexcept {
|
||||
return data_->return_type;
|
||||
}
|
||||
|
||||
inline any_type function_type::get_argument_type(std::size_t index) const noexcept {
|
||||
return index < data_->argument_types.size() ? data_->argument_types[index] : any_type{};
|
||||
}
|
||||
|
||||
inline const std::vector<any_type>& function_type::get_argument_types() const noexcept {
|
||||
return data_->argument_types;
|
||||
}
|
||||
}
|
||||
61
headers/meta.hpp/meta_types/member_type.hpp
Normal file
61
headers/meta.hpp/meta_types/member_type.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/member_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
struct member_tag {};
|
||||
|
||||
template < member_kind Member >
|
||||
member_type_data_ptr member_type_data::get() {
|
||||
static member_type_data_ptr data = std::make_shared<member_type_data>(type_list<Member>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
member_type_data::member_type_data(type_list<Member>)
|
||||
: type_data_base{type_id{type_list<member_tag<Member>>{}}, type_kind::member_}
|
||||
, flags{member_traits<Member>::make_flags()}
|
||||
, owner_type{resolve_type<typename member_traits<Member>::class_type>()}
|
||||
, value_type{resolve_type<typename member_traits<Member>::value_type>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline member_type::member_type(detail::member_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool member_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline member_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id member_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<member_flags> member_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline class_type member_type::get_owner_type() const noexcept {
|
||||
return data_->owner_type;
|
||||
}
|
||||
|
||||
inline any_type member_type::get_value_type() const noexcept {
|
||||
return data_->value_type;
|
||||
}
|
||||
}
|
||||
74
headers/meta.hpp/meta_types/method_type.hpp
Normal file
74
headers/meta.hpp/meta_types/method_type.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/method_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < method_kind Method >
|
||||
struct method_tag {};
|
||||
|
||||
template < method_kind Method >
|
||||
method_type_data_ptr method_type_data::get() {
|
||||
static method_type_data_ptr data = std::make_shared<method_type_data>(type_list<Method>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
method_type_data::method_type_data(type_list<Method>)
|
||||
: type_data_base{type_id{type_list<method_tag<Method>>{}}, type_kind::method_}
|
||||
, flags{method_traits<Method>::make_flags()}
|
||||
, owner_type{resolve_type<typename method_traits<Method>::class_type>()}
|
||||
, return_type{resolve_type<typename method_traits<Method>::return_type>()}
|
||||
, argument_types{method_traits<Method>::make_argument_types()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline method_type::method_type(detail::method_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool method_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline method_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id method_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<method_flags> method_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t method_type::get_arity() const noexcept {
|
||||
return data_->argument_types.size();
|
||||
}
|
||||
|
||||
inline class_type method_type::get_owner_type() const noexcept {
|
||||
return data_->owner_type;
|
||||
}
|
||||
|
||||
inline any_type method_type::get_return_type() const noexcept {
|
||||
return data_->return_type;
|
||||
}
|
||||
|
||||
inline any_type method_type::get_argument_type(std::size_t index) const noexcept {
|
||||
return index < data_->argument_types.size() ? data_->argument_types[index] : any_type{};
|
||||
}
|
||||
|
||||
inline const std::vector<any_type>& method_type::get_argument_types() const noexcept {
|
||||
return data_->argument_types;
|
||||
}
|
||||
}
|
||||
56
headers/meta.hpp/meta_types/number_type.hpp
Normal file
56
headers/meta.hpp/meta_types/number_type.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/number_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < number_kind Number >
|
||||
struct number_tag {};
|
||||
|
||||
template < number_kind Number >
|
||||
number_type_data_ptr number_type_data::get() {
|
||||
static number_type_data_ptr data = std::make_shared<number_type_data>(type_list<Number>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < number_kind Number >
|
||||
number_type_data::number_type_data(type_list<Number>)
|
||||
: type_data_base{type_id{type_list<number_tag<Number>>{}}, type_kind::number_}
|
||||
, flags{number_traits<Number>::make_flags()}
|
||||
, size{number_traits<Number>::size} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline number_type::number_type(detail::number_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool number_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline number_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id number_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<number_flags> number_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline std::size_t number_type::get_size() const noexcept {
|
||||
return data_->size;
|
||||
}
|
||||
}
|
||||
56
headers/meta.hpp/meta_types/pointer_type.hpp
Normal file
56
headers/meta.hpp/meta_types/pointer_type.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/pointer_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < pointer_kind Pointer >
|
||||
struct pointer_tag {};
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
pointer_type_data_ptr pointer_type_data::get() {
|
||||
static pointer_type_data_ptr data = std::make_shared<pointer_type_data>(type_list<Pointer>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < pointer_kind Pointer >
|
||||
pointer_type_data::pointer_type_data(type_list<Pointer>)
|
||||
: type_data_base{type_id{type_list<pointer_tag<Pointer>>{}}, type_kind::pointer_}
|
||||
, flags{pointer_traits<Pointer>::make_flags()}
|
||||
, data_type{resolve_type<typename pointer_traits<Pointer>::data_type>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline pointer_type::pointer_type(detail::pointer_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool pointer_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline pointer_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id pointer_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<pointer_flags> pointer_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline any_type pointer_type::get_data_type() const noexcept {
|
||||
return data_->data_type;
|
||||
}
|
||||
}
|
||||
56
headers/meta.hpp/meta_types/reference_type.hpp
Normal file
56
headers/meta.hpp/meta_types/reference_type.hpp
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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/reference_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < reference_kind Reference >
|
||||
struct reference_tag {};
|
||||
|
||||
template < reference_kind Reference >
|
||||
reference_type_data_ptr reference_type_data::get() {
|
||||
static reference_type_data_ptr data = std::make_shared<reference_type_data>(type_list<Reference>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < reference_kind Reference >
|
||||
reference_type_data::reference_type_data(type_list<Reference>)
|
||||
: type_data_base{type_id{type_list<reference_tag<Reference>>{}}, type_kind::reference_}
|
||||
, flags{reference_traits<Reference>::make_flags()}
|
||||
, data_type{resolve_type<typename reference_traits<Reference>::data_type>()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline reference_type::reference_type(detail::reference_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool reference_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline reference_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id reference_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<reference_flags> reference_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
|
||||
inline any_type reference_type::get_data_type() const noexcept {
|
||||
return data_->data_type;
|
||||
}
|
||||
}
|
||||
51
headers/meta.hpp/meta_types/void_type.hpp
Normal file
51
headers/meta.hpp/meta_types/void_type.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_types.hpp"
|
||||
|
||||
#include "../meta_traits/void_traits.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < void_kind Void >
|
||||
struct void_tag {};
|
||||
|
||||
template < void_kind Void >
|
||||
void_type_data_ptr void_type_data::get() {
|
||||
static void_type_data_ptr data = std::make_shared<void_type_data>(type_list<Void>{});
|
||||
return data;
|
||||
}
|
||||
|
||||
template < void_kind Void >
|
||||
void_type_data::void_type_data(type_list<Void>)
|
||||
: type_data_base{type_id{type_list<void_tag<Void>>{}}, type_kind::void_}
|
||||
, flags{void_traits<Void>::make_flags()} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline void_type::void_type(detail::void_type_data_ptr data)
|
||||
: data_{std::move(data)} {}
|
||||
|
||||
inline bool void_type::is_valid() const noexcept {
|
||||
return !!data_;
|
||||
}
|
||||
|
||||
inline void_type::operator bool() const noexcept {
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline type_id void_type::get_id() const noexcept {
|
||||
return data_->id;
|
||||
}
|
||||
|
||||
inline bitflags<void_flags> void_type::get_flags() const noexcept {
|
||||
return data_->flags;
|
||||
}
|
||||
}
|
||||
238
headers/meta.hpp/meta_utilities.hpp
Normal file
238
headers/meta.hpp/meta_utilities.hpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "meta_base.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class value final {
|
||||
public:
|
||||
value() = delete;
|
||||
|
||||
value(value&& other);
|
||||
value(const value& other);
|
||||
|
||||
value& operator=(value&& other);
|
||||
value& operator=(const value& other);
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::arg>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::inst>, int> = 0 >
|
||||
explicit value(T&& val);
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::arg>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::inst>, int> = 0 >
|
||||
value& operator=(T&& val);
|
||||
|
||||
void swap(value& other) noexcept;
|
||||
|
||||
const any_type& get_type() const noexcept;
|
||||
|
||||
void* data() noexcept;
|
||||
const void* data() const noexcept;
|
||||
const void* cdata() const noexcept;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
Tp& cast() &;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
Tp&& cast() &&;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
const Tp& cast() const &;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
const Tp&& cast() const &&;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
Tp* try_cast() noexcept;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T> >
|
||||
const Tp* try_cast() const noexcept;
|
||||
|
||||
template < typename T >
|
||||
friend bool operator==(const value& l, const T& r);
|
||||
template < typename T >
|
||||
friend bool operator==(const T& l, const value& r);
|
||||
friend bool operator==(const value& l, const value& r);
|
||||
|
||||
friend std::istream& operator>>(std::istream& os, value& v);
|
||||
friend std::ostream& operator<<(std::ostream& os, const value& v);
|
||||
private:
|
||||
struct traits;
|
||||
std::any raw_{};
|
||||
const traits* traits_{};
|
||||
};
|
||||
|
||||
inline void swap(value& l, value& r) noexcept {
|
||||
l.swap(r);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
class arg_base {
|
||||
public:
|
||||
enum class ref_types {
|
||||
ref,
|
||||
rref,
|
||||
cref,
|
||||
crref,
|
||||
};
|
||||
public:
|
||||
arg_base() = delete;
|
||||
|
||||
arg_base(arg_base&&) = delete;
|
||||
arg_base& operator=(arg_base&&) = delete;
|
||||
|
||||
arg_base(const arg_base&) = delete;
|
||||
arg_base& operator=(const arg_base&) = delete;
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_pointer_v<T> || std::is_lvalue_reference_v<T>
|
||||
, int> = 0 >
|
||||
explicit arg_base(type_list<T>);
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_rvalue_reference_v<T> ||
|
||||
(!std::is_pointer_v<T> && !std::is_reference_v<T>)
|
||||
, int> = 0 >
|
||||
explicit arg_base(type_list<T>);
|
||||
|
||||
explicit arg_base(value& v);
|
||||
explicit arg_base(value&& v);
|
||||
explicit arg_base(const value& v);
|
||||
explicit arg_base(const value&& v);
|
||||
|
||||
bool is_const() const noexcept;
|
||||
bool is_lvalue() const noexcept;
|
||||
bool is_rvalue() const noexcept;
|
||||
|
||||
any_type get_raw_type() const noexcept;
|
||||
ref_types get_ref_type() const noexcept;
|
||||
|
||||
template < typename To >
|
||||
bool can_cast_to() const noexcept;
|
||||
private:
|
||||
any_type raw_type_{};
|
||||
ref_types ref_type_{};
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
class arg final : public arg_base {
|
||||
public:
|
||||
arg() = delete;
|
||||
|
||||
arg(arg&&) = delete;
|
||||
arg& operator=(arg&&) = delete;
|
||||
|
||||
arg(const arg&) = delete;
|
||||
arg& operator=(const arg&) = delete;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, arg>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, inst>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0 >
|
||||
explicit arg(T&& v);
|
||||
|
||||
explicit arg(value& v);
|
||||
explicit arg(value&& v);
|
||||
explicit arg(const value& v);
|
||||
explicit arg(const value&& v);
|
||||
|
||||
template < typename To >
|
||||
To cast() const;
|
||||
private:
|
||||
void* data_{};
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
class inst_base {
|
||||
public:
|
||||
enum class ref_types {
|
||||
ref,
|
||||
rref,
|
||||
cref,
|
||||
crref,
|
||||
};
|
||||
public:
|
||||
inst_base() = delete;
|
||||
|
||||
inst_base(inst_base&&) = delete;
|
||||
inst_base& operator=(inst_base&&) = delete;
|
||||
|
||||
inst_base(const inst_base&) = delete;
|
||||
inst_base& operator=(const inst_base&) = delete;
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>
|
||||
, int> = 0>
|
||||
explicit inst_base(type_list<T>);
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_class_v<T> ||
|
||||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>)
|
||||
, int> = 0>
|
||||
explicit inst_base(type_list<T>);
|
||||
|
||||
explicit inst_base(value& v);
|
||||
explicit inst_base(value&& v);
|
||||
explicit inst_base(const value& v);
|
||||
explicit inst_base(const value&& v);
|
||||
|
||||
bool is_const() const noexcept;
|
||||
bool is_lvalue() const noexcept;
|
||||
bool is_rvalue() const noexcept;
|
||||
|
||||
any_type get_raw_type() const noexcept;
|
||||
ref_types get_ref_type() const noexcept;
|
||||
|
||||
template < typename To >
|
||||
bool can_cast_to() const noexcept;
|
||||
private:
|
||||
any_type raw_type_{};
|
||||
ref_types ref_type_{};
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
class inst final : public inst_base {
|
||||
public:
|
||||
inst() = delete;
|
||||
|
||||
inst(inst&&) = delete;
|
||||
inst& operator=(inst&&) = delete;
|
||||
|
||||
inst(const inst&) = delete;
|
||||
inst& operator=(const inst&) = delete;
|
||||
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, arg>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, inst>, int> = 0
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> = 0 >
|
||||
explicit inst(T&& v);
|
||||
|
||||
explicit inst(value& v);
|
||||
explicit inst(value&& v);
|
||||
explicit inst(const value& v);
|
||||
explicit inst(const value&& v);
|
||||
|
||||
template < typename To >
|
||||
decltype(auto) cast() const;
|
||||
private:
|
||||
void* data_{};
|
||||
};
|
||||
}
|
||||
205
headers/meta.hpp/meta_utilities/arg.hpp
Normal file
205
headers/meta.hpp/meta_utilities/arg.hpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_utilities.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_pointer_v<T> || std::is_lvalue_reference_v<T>
|
||||
, int> >
|
||||
arg_base::arg_base(type_list<T>)
|
||||
: raw_type_{resolve_type<std::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::cref : ref_types::ref} {}
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_rvalue_reference_v<T> ||
|
||||
(!std::is_pointer_v<T> && !std::is_reference_v<T>)
|
||||
, int> >
|
||||
arg_base::arg_base(type_list<T>)
|
||||
: raw_type_{resolve_type<std::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::crref : ref_types::rref} {}
|
||||
|
||||
inline arg_base::arg_base(value& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::ref} {}
|
||||
|
||||
inline arg_base::arg_base(value&& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::rref} {}
|
||||
|
||||
inline arg_base::arg_base(const value& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::cref} {}
|
||||
|
||||
inline arg_base::arg_base(const value&& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::crref} {}
|
||||
|
||||
inline bool arg_base::is_const() const noexcept {
|
||||
return ref_type_ == ref_types::cref
|
||||
|| ref_type_ == ref_types::crref;
|
||||
}
|
||||
|
||||
inline bool arg_base::is_lvalue() const noexcept {
|
||||
return ref_type_ == ref_types::ref
|
||||
|| ref_type_ == ref_types::cref;
|
||||
}
|
||||
|
||||
inline bool arg_base::is_rvalue() const noexcept {
|
||||
return ref_type_ == ref_types::rref
|
||||
|| ref_type_ == ref_types::crref;
|
||||
}
|
||||
|
||||
inline any_type arg_base::get_raw_type() const noexcept {
|
||||
return raw_type_;
|
||||
}
|
||||
|
||||
inline arg_base::ref_types arg_base::get_ref_type() const noexcept {
|
||||
return ref_type_;
|
||||
}
|
||||
|
||||
template < typename To >
|
||||
bool arg_base::can_cast_to() const noexcept {
|
||||
if constexpr ( std::is_pointer_v<To> ) {
|
||||
using to_raw_type = std::remove_cv_t<To>;
|
||||
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return get_raw_type() == resolve_type<to_raw_type>()
|
||||
|| get_raw_type() == resolve_type<to_raw_ptr_type*>();
|
||||
}
|
||||
|
||||
if constexpr ( std::is_reference_v<To> ) {
|
||||
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
|
||||
|
||||
if constexpr ( !to_const ) {
|
||||
if ( is_const() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
if constexpr ( !to_const ) {
|
||||
if ( is_rvalue() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<To> ) {
|
||||
if ( !is_rvalue() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
using to_raw_type = std::remove_cvref_t<To>;
|
||||
if ( get_raw_type() == resolve_type<to_raw_type>() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if constexpr ( to_const && std::is_pointer_v<to_raw_type> ) {
|
||||
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return get_raw_type() == resolve_type<to_raw_ptr_type*>();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
|
||||
using to_raw_type = std::remove_cv_t<To>;
|
||||
if ( get_raw_type() != resolve_type<to_raw_type>() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (get_ref_type() == ref_types::ref && std::is_constructible_v<To, to_raw_type&>)
|
||||
|| (get_ref_type() == ref_types::cref && std::is_constructible_v<To, const to_raw_type&>)
|
||||
|| (get_ref_type() == ref_types::rref && std::is_constructible_v<To, to_raw_type&&>)
|
||||
|| (get_ref_type() == ref_types::crref && std::is_constructible_v<To, const to_raw_type&&>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, typename Tp
|
||||
, std::enable_if_t<!std::is_same_v<Tp, arg>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, inst>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> >
|
||||
arg::arg(T&& v)
|
||||
: arg_base{type_list<T&&>{}}
|
||||
, data_{const_cast<std::remove_cvref_t<T>*>(std::addressof(v))} {}
|
||||
|
||||
inline arg::arg(value& v)
|
||||
: arg_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline arg::arg(value&& v)
|
||||
: arg_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline arg::arg(const value& v)
|
||||
: arg_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline arg::arg(const value&& v)
|
||||
: arg_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
template < typename To >
|
||||
To arg::cast() const {
|
||||
if ( !can_cast_to<To>() ) {
|
||||
throw std::logic_error("bad argument cast");
|
||||
}
|
||||
|
||||
if constexpr ( std::is_pointer_v<To> ) {
|
||||
return *static_cast<To*>(data_);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_reference_v<To> ) {
|
||||
using raw_type = std::remove_cvref_t<To>;
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
return *static_cast<raw_type*>(data_);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<To> ) {
|
||||
return std::move(*static_cast<raw_type*>(data_));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
|
||||
using raw_type = std::remove_cv_t<To>;
|
||||
|
||||
if ( get_ref_type() == ref_types::ref ) {
|
||||
if constexpr ( std::is_constructible_v<To, raw_type&> ) {
|
||||
return To{*static_cast<raw_type*>(data_)};
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_ref_type() == ref_types::cref ) {
|
||||
if constexpr ( std::is_constructible_v<To, const raw_type&> ) {
|
||||
return To{std::as_const(*static_cast<raw_type*>(data_))};
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_ref_type() == ref_types::rref ) {
|
||||
if constexpr ( std::is_constructible_v<To, raw_type&&> ) {
|
||||
return To{std::move(*static_cast<raw_type*>(data_))};
|
||||
}
|
||||
}
|
||||
|
||||
if ( get_ref_type() == ref_types::crref ) {
|
||||
if constexpr ( std::is_constructible_v<To, const raw_type&&> ) {
|
||||
return To{std::move(std::as_const(*static_cast<raw_type*>(data_)))};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw std::logic_error("bad argument cast");
|
||||
}
|
||||
}
|
||||
148
headers/meta.hpp/meta_utilities/inst.hpp
Normal file
148
headers/meta.hpp/meta_utilities/inst.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_utilities.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>
|
||||
, int> >
|
||||
inst_base::inst_base(type_list<T>)
|
||||
: raw_type_{resolve_type<std::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::cref : ref_types::ref} {}
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
std::is_class_v<T> ||
|
||||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>)
|
||||
, int> >
|
||||
inst_base::inst_base(type_list<T>)
|
||||
: raw_type_{resolve_type<std::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::crref : ref_types::rref} {}
|
||||
|
||||
inline inst_base::inst_base(value& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::ref} {}
|
||||
|
||||
inline inst_base::inst_base(value&& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::rref} {}
|
||||
|
||||
inline inst_base::inst_base(const value& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::cref} {}
|
||||
|
||||
inline inst_base::inst_base(const value&& v)
|
||||
: raw_type_{v.get_type()}
|
||||
, ref_type_{ref_types::crref} {}
|
||||
|
||||
inline bool inst_base::is_const() const noexcept {
|
||||
return ref_type_ == ref_types::cref
|
||||
|| ref_type_ == ref_types::crref;
|
||||
}
|
||||
|
||||
inline bool inst_base::is_lvalue() const noexcept {
|
||||
return ref_type_ == ref_types::ref
|
||||
|| ref_type_ == ref_types::cref;
|
||||
}
|
||||
|
||||
inline bool inst_base::is_rvalue() const noexcept {
|
||||
return ref_type_ == ref_types::rref
|
||||
|| ref_type_ == ref_types::crref;
|
||||
}
|
||||
|
||||
inline any_type inst_base::get_raw_type() const noexcept {
|
||||
return raw_type_;
|
||||
}
|
||||
|
||||
inline inst_base::ref_types inst_base::get_ref_type() const noexcept {
|
||||
return ref_type_;
|
||||
}
|
||||
|
||||
template < typename To >
|
||||
bool inst_base::can_cast_to() const noexcept {
|
||||
static_assert(
|
||||
std::is_class_v<To> ||
|
||||
(std::is_reference_v<To> && std::is_class_v<std::remove_reference_t<To>>));
|
||||
|
||||
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
|
||||
|
||||
if constexpr ( !to_const ) {
|
||||
if ( is_const() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
if ( !is_lvalue() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<To> ) {
|
||||
if ( !is_rvalue() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
using to_raw_type = std::remove_cvref_t<To>;
|
||||
return get_raw_type() == resolve_type<to_raw_type>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, typename Tp
|
||||
, std::enable_if_t<!std::is_same_v<Tp, arg>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, inst>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int> >
|
||||
inst::inst(T&& v)
|
||||
: inst_base{type_list<T&&>{}}
|
||||
, data_{const_cast<std::remove_cvref_t<T>*>(std::addressof(v))} {}
|
||||
|
||||
inline inst::inst(value& v)
|
||||
: inst_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline inst::inst(value&& v)
|
||||
: inst_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline inst::inst(const value& v)
|
||||
: inst_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
inline inst::inst(const value&& v)
|
||||
: inst_base{v}
|
||||
, data_{const_cast<void*>(v.data())} {}
|
||||
|
||||
template < typename To >
|
||||
decltype(auto) inst::cast() const {
|
||||
if ( !can_cast_to<To>() ) {
|
||||
throw std::logic_error("bad inst cast");
|
||||
}
|
||||
|
||||
if constexpr ( std::is_reference_v<To> ) {
|
||||
using raw_type_with_cv = std::remove_reference_t<To>;
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
return *static_cast<raw_type_with_cv*>(data_);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<To> ) {
|
||||
return std::move(*static_cast<raw_type_with_cv*>(data_));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( !std::is_reference_v<To>) {
|
||||
using raw_type_with_cv = To;
|
||||
return *static_cast<raw_type_with_cv*>(data_);
|
||||
}
|
||||
}
|
||||
}
|
||||
306
headers/meta.hpp/meta_utilities/value.hpp
Normal file
306
headers/meta.hpp/meta_utilities/value.hpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_utilities.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, typename = void >
|
||||
struct has_value_type_equality_operator
|
||||
: std::false_type {};
|
||||
|
||||
template < typename T >
|
||||
struct has_value_type_equality_operator<T, std::void_t<decltype(
|
||||
std::declval<const T&>() == std::declval<const T&>()
|
||||
)>> : std::true_type {};
|
||||
|
||||
template < typename T >
|
||||
inline constexpr bool has_value_type_equality_operator_v = has_value_type_equality_operator<T>::value;
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
has_value_type_equality_operator_v<T>
|
||||
, int> = 0 >
|
||||
bool value_equals_function(const value& l, const value& r) {
|
||||
assert(l.get_type() == r.get_type());
|
||||
return l.cast<T>() == r.cast<T>();
|
||||
}
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
!has_value_type_equality_operator_v<T>
|
||||
, int> = 0 >
|
||||
bool value_equals_function([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) {
|
||||
throw std::logic_error("value type doesn't have equality operator");
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, typename = void >
|
||||
struct has_value_type_istream_operator
|
||||
: std::false_type {};
|
||||
|
||||
template < typename T >
|
||||
struct has_value_type_istream_operator<T, std::void_t<decltype(
|
||||
std::declval<std::istream&>() >> std::declval<T&>()
|
||||
)>> : std::true_type {};
|
||||
|
||||
template < typename T >
|
||||
inline constexpr bool has_value_type_istream_operator_v = has_value_type_istream_operator<T>::value;
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
has_value_type_istream_operator_v<T>
|
||||
, int> = 0 >
|
||||
void value_istream_function(std::istream& os, value& v) {
|
||||
os >> v.cast<T>();
|
||||
}
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
!has_value_type_istream_operator_v<T>
|
||||
, int> = 0 >
|
||||
void value_istream_function([[maybe_unused]] std::istream& os, [[maybe_unused]] value& v) {
|
||||
throw std::logic_error("value type doesn't have istream operator");
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename T, typename = void >
|
||||
struct has_value_type_ostream_operator
|
||||
: std::false_type {};
|
||||
|
||||
template < typename T >
|
||||
struct has_value_type_ostream_operator<T, std::void_t<decltype(
|
||||
std::declval<std::ostream&>() << std::declval<const T&>()
|
||||
)>> : std::true_type {};
|
||||
|
||||
template < typename T >
|
||||
inline constexpr bool has_value_type_ostream_operator_v = has_value_type_ostream_operator<T>::value;
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
has_value_type_ostream_operator_v<T>
|
||||
, int> = 0 >
|
||||
void value_ostream_function(std::ostream& os, const value& v) {
|
||||
os << v.cast<T>();
|
||||
}
|
||||
|
||||
template < typename T, std::enable_if_t<
|
||||
!has_value_type_ostream_operator_v<T>
|
||||
, int> = 0 >
|
||||
void value_ostream_function([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) {
|
||||
throw std::logic_error("value type doesn't have ostream operator");
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
struct value::traits final {
|
||||
const any_type type;
|
||||
|
||||
void* (*const data)(value&) noexcept;
|
||||
const void* (*const cdata)(const value&) noexcept;
|
||||
|
||||
bool (*const equals)(const value&, const value&);
|
||||
|
||||
void (*const move_ctor)(std::any&, value&&);
|
||||
void (*const copy_ctor)(std::any&, const value&);
|
||||
|
||||
void (*const istream)(std::istream&, value&);
|
||||
void (*const ostream)(std::ostream&, const value&);
|
||||
|
||||
template < typename T >
|
||||
static const traits* get() noexcept;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
const value::traits* value::traits::get() noexcept {
|
||||
static const traits traits{
|
||||
// type
|
||||
resolve_type<T>(),
|
||||
|
||||
// data
|
||||
+[](value& v) noexcept -> void* {
|
||||
return v.try_cast<T>();
|
||||
},
|
||||
|
||||
// cdata
|
||||
+[](const value& v) noexcept -> const void* {
|
||||
return v.try_cast<T>();
|
||||
},
|
||||
|
||||
// equals
|
||||
&detail::value_equals_function<T>,
|
||||
|
||||
// move_ctor
|
||||
+[](std::any& dst, value&& src) {
|
||||
if constexpr ( std::is_move_constructible_v<T> ) {
|
||||
dst.emplace<T>(std::move(src).cast<T>());
|
||||
} else {
|
||||
throw std::logic_error("value type is not move constructible");
|
||||
}
|
||||
},
|
||||
|
||||
// copy_ctor
|
||||
+[](std::any& dst, const value& src) {
|
||||
if constexpr ( std::is_copy_constructible_v<T> ) {
|
||||
dst.emplace<T>(src.cast<T>());
|
||||
} else {
|
||||
throw std::logic_error("value type is not copy constructible");
|
||||
}
|
||||
},
|
||||
|
||||
// istream
|
||||
&detail::value_istream_function<T>,
|
||||
|
||||
// ostream
|
||||
&detail::value_ostream_function<T>,
|
||||
};
|
||||
return &traits;
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline value::value(value&& other) {
|
||||
traits_ = other.traits_;
|
||||
traits_->move_ctor(raw_, std::move(other));
|
||||
}
|
||||
|
||||
inline value::value(const value& other) {
|
||||
traits_ = other.traits_;
|
||||
traits_->copy_ctor(raw_, other);
|
||||
}
|
||||
|
||||
inline value& value::operator=(value&& other) {
|
||||
if ( this != &other ) {
|
||||
traits_ = other.traits_;
|
||||
traits_->move_ctor(raw_, std::move(other));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline value& value::operator=(const value& other) {
|
||||
if ( this != &other ) {
|
||||
traits_ = other.traits_;
|
||||
traits_->copy_ctor(raw_, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename T, typename Tp
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::arg>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::inst>, int> >
|
||||
value::value(T&& val)
|
||||
: raw_{std::forward<T>(val)}
|
||||
, traits_{traits::get<Tp>()} {}
|
||||
|
||||
template < typename T, typename Tp
|
||||
, std::enable_if_t<!std::is_same_v<Tp, value>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::arg>, int>
|
||||
, std::enable_if_t<!std::is_same_v<Tp, detail::inst>, int> >
|
||||
value& value::operator=(T&& val) {
|
||||
raw_ = std::forward<T>(val);
|
||||
traits_ = resolve_type<Tp>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void value::swap(value& other) noexcept {
|
||||
using std::swap;
|
||||
swap(raw_, other.raw_);
|
||||
swap(traits_, other.traits_);
|
||||
}
|
||||
|
||||
inline const any_type& value::get_type() const noexcept {
|
||||
return traits_->type;
|
||||
}
|
||||
|
||||
inline void* value::data() noexcept {
|
||||
return traits_->data(*this);
|
||||
}
|
||||
|
||||
inline const void* value::data() const noexcept {
|
||||
return traits_->cdata(*this);
|
||||
}
|
||||
|
||||
inline const void* value::cdata() const noexcept {
|
||||
return traits_->cdata(*this);
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
Tp& value::cast() & {
|
||||
if ( get_type() != resolve_type<Tp>() ) {
|
||||
throw std::logic_error("bad value cast");
|
||||
}
|
||||
return std::any_cast<Tp&>(raw_);
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
Tp&& value::cast() && {
|
||||
if ( get_type() != resolve_type<Tp>() ) {
|
||||
throw std::logic_error("bad value cast");
|
||||
}
|
||||
return std::move(std::any_cast<Tp&>(raw_));
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
const Tp& value::cast() const & {
|
||||
if ( get_type() != resolve_type<Tp>() ) {
|
||||
throw std::logic_error("bad value cast");
|
||||
}
|
||||
return std::any_cast<const Tp&>(raw_);
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
const Tp&& value::cast() const && {
|
||||
if ( get_type() != resolve_type<Tp>() ) {
|
||||
throw std::logic_error("bad value cast");
|
||||
}
|
||||
return std::move(std::any_cast<const Tp&>(raw_));
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
Tp* value::try_cast() noexcept {
|
||||
return std::any_cast<Tp>(&raw_);
|
||||
}
|
||||
|
||||
template < typename T, typename Tp >
|
||||
const Tp* value::try_cast() const noexcept {
|
||||
return std::any_cast<Tp>(&raw_);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename T >
|
||||
bool operator==(const value& l, const T& r) {
|
||||
return l.get_type() == resolve_type<T>()
|
||||
&& std::equal_to<>{}(l.cast<T>(), r);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool operator==(const T& l, const value& r) {
|
||||
return resolve_type<T>() == r.get_type()
|
||||
&& std::equal_to<>{}(l, r.cast<T>());
|
||||
}
|
||||
|
||||
inline bool operator==(const value& l, const value& r) {
|
||||
return l.get_type() == r.get_type()
|
||||
&& l.traits_->equals(l, r);
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& is, value& v) {
|
||||
v.traits_->istream(is, v);
|
||||
return is;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const value& v) {
|
||||
v.traits_->ostream(os, v);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
38
untests/examples/class_example.cpp
Normal file
38
untests/examples/class_example.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct base_clazz {
|
||||
};
|
||||
|
||||
struct derived_clazz final : base_clazz {
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/class") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<derived_clazz>()
|
||||
.base_<base_clazz>();
|
||||
|
||||
const meta::class_type base_clazz_type = meta::resolve_type<base_clazz>();
|
||||
REQUIRE(base_clazz_type);
|
||||
|
||||
const meta::class_type derived_clazz_type = meta::resolve_type<derived_clazz>();
|
||||
REQUIRE(derived_clazz_type);
|
||||
|
||||
CHECK(base_clazz_type.is_base_of<derived_clazz>());
|
||||
CHECK(derived_clazz_type.is_derived_from<base_clazz>());
|
||||
|
||||
const meta::class_type int_vector_type = meta::resolve_type<std::vector<int>>();
|
||||
REQUIRE(int_vector_type);
|
||||
CHECK(int_vector_type.get_arity() == 2);
|
||||
CHECK(int_vector_type.get_argument_type(0) == meta::resolve_type<int>());
|
||||
CHECK(int_vector_type.get_argument_type(1) == meta::resolve_type<std::allocator<int>>());
|
||||
}
|
||||
99
untests/examples/complex_example.cpp
Normal file
99
untests/examples/complex_example.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
ivec2() = default;
|
||||
ivec2(int v) : x{v}, y{v} {}
|
||||
ivec2(int x, int y) : x{x}, y{y} {}
|
||||
|
||||
int dot(const ivec2& other) const noexcept {
|
||||
return x * other.x + y * other.y;
|
||||
}
|
||||
|
||||
int length2() const noexcept {
|
||||
return dot(*this);
|
||||
}
|
||||
|
||||
friend bool operator==(const ivec2& l, const ivec2& r) noexcept {
|
||||
return l.x == r.x && l.y == r.y;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/complex") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<ivec2>()
|
||||
.ctor_<>()
|
||||
.ctor_<int>()
|
||||
.ctor_<int, int>()
|
||||
.member_("x", &ivec2::x)
|
||||
.member_("y", &ivec2::y)
|
||||
.method_("dot", &ivec2::dot)
|
||||
.method_("length2", &ivec2::length2);
|
||||
|
||||
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
|
||||
|
||||
const meta::member ivec2_x = ivec2_type.get_member("x");
|
||||
const meta::member ivec2_y = ivec2_type.get_member("y");
|
||||
|
||||
const meta::method ivec2_dot = ivec2_type.get_method("dot");
|
||||
const meta::method ivec2_length2 = ivec2_type.get_method("length2");
|
||||
|
||||
{
|
||||
const ivec2 v = ivec2_type.get_ctor_with<>().invoke().cast<ivec2>();
|
||||
CHECK(v == ivec2{});
|
||||
|
||||
CHECK(ivec2_x.get(v) == 0);
|
||||
CHECK(ivec2_y.get(v) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const ivec2 v = ivec2_type.get_ctor_with<int>().invoke(3).cast<ivec2>();
|
||||
CHECK(v == ivec2{3});
|
||||
|
||||
CHECK(ivec2_x.get(v) == 3);
|
||||
CHECK(ivec2_y.get(v) == 3);
|
||||
}
|
||||
|
||||
{
|
||||
const meta::value v = ivec2_type.get_ctor_with<int, int>().invoke(1, 2);
|
||||
CHECK(v == ivec2{1, 2});
|
||||
|
||||
CHECK(ivec2_x.get(v) == 1);
|
||||
CHECK(ivec2_y.get(v) == 2);
|
||||
}
|
||||
|
||||
{
|
||||
meta::value v = ivec2_type.get_ctor_with<int, int>().invoke(1, 2);
|
||||
|
||||
ivec2_x.set(v, 10);
|
||||
ivec2_y.set(v, 20);
|
||||
|
||||
CHECK(ivec2_x.get(v) == 10);
|
||||
CHECK(ivec2_y.get(v) == 20);
|
||||
}
|
||||
|
||||
{
|
||||
const meta::value v0 = ivec2_type.get_ctor_with<int, int>().invoke(1, 2);
|
||||
const meta::value v1 = ivec2_type.get_ctor_with<int, int>().invoke(3, 4);
|
||||
|
||||
CHECK(ivec2_dot.invoke(v0, v1) == 1 * 3 + 2 * 4);
|
||||
}
|
||||
|
||||
{
|
||||
const meta::value v = ivec2_type.get_ctor_with<int, int>().invoke(3, 4);
|
||||
|
||||
CHECK(ivec2_length2.invoke(v) == 3 * 3 + 4 * 4);
|
||||
}
|
||||
}
|
||||
36
untests/examples/enum_example.cpp
Normal file
36
untests/examples/enum_example.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class color : unsigned {
|
||||
red = 0xFF0000,
|
||||
green = 0x00FF00,
|
||||
blue = 0x0000FF,
|
||||
white = red | green | blue,
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/enum") {
|
||||
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_type color_type = meta::resolve_type<color>();
|
||||
REQUIRE(color_type);
|
||||
|
||||
CHECK(color_type.get_underlying_type() == meta::resolve_type<unsigned>());
|
||||
|
||||
CHECK(color_type.get_evalue("green").get_index().name == "green");
|
||||
CHECK(color_type.get_evalue("green").get_value() == color::green);
|
||||
CHECK_FALSE(color_type.get_evalue("yellow"));
|
||||
}
|
||||
37
untests/examples/member_example.cpp
Normal file
37
untests/examples/member_example.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 final {
|
||||
int x{};
|
||||
int y{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/member") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<ivec2>()
|
||||
.member_("x", &ivec2::x)
|
||||
.member_("y", &ivec2::y);
|
||||
|
||||
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
|
||||
REQUIRE(ivec2_type);
|
||||
|
||||
CHECK(ivec2_type.get_members().size() == 2);
|
||||
|
||||
const meta::member ivec2_x = ivec2_type.get_member("x");
|
||||
REQUIRE(ivec2_x);
|
||||
|
||||
CHECK(ivec2_x.get_index().name == "x");
|
||||
CHECK(ivec2_x.get_type() == meta::resolve_type<decltype(&ivec2::x)>());
|
||||
|
||||
CHECK(ivec2_x.get_type().get_owner_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(ivec2_x.get_type().get_value_type() == meta::resolve_type<int>());
|
||||
}
|
||||
48
untests/examples/method_example.cpp
Normal file
48
untests/examples/method_example.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 final {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
int dot(const ivec2& other) const noexcept {
|
||||
return x * other.x + y * other.y;
|
||||
}
|
||||
|
||||
int length2() const noexcept {
|
||||
return dot(*this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/method") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<ivec2>()
|
||||
.member_("x", &ivec2::x)
|
||||
.member_("y", &ivec2::y)
|
||||
.method_("dot", &ivec2::dot)
|
||||
.method_("length2", &ivec2::length2);
|
||||
|
||||
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
|
||||
REQUIRE(ivec2_type);
|
||||
|
||||
CHECK(ivec2_type.get_methods().size() == 2);
|
||||
|
||||
const meta::method ivec2_dot = ivec2_type.get_method("dot");
|
||||
REQUIRE(ivec2_dot);
|
||||
|
||||
CHECK(ivec2_dot.get_index().name == "dot");
|
||||
CHECK(ivec2_dot.get_type() == meta::resolve_type<decltype(&ivec2::dot)>());
|
||||
|
||||
CHECK(ivec2_dot.get_type().get_arity() == 1);
|
||||
CHECK(ivec2_dot.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(ivec2_dot.get_type().get_argument_type(0) == meta::resolve_type<const ivec2&>());
|
||||
}
|
||||
31
untests/examples/number_example.cpp
Normal file
31
untests/examples/number_example.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
}
|
||||
|
||||
TEST_CASE("meta/examples/number") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
{
|
||||
const meta::number_type int_type = meta::resolve_type<int>();
|
||||
REQUIRE(int_type);
|
||||
|
||||
CHECK(int_type.get_flags().has(meta::number_flags::is_signed));
|
||||
CHECK(int_type.get_size() == sizeof(int));
|
||||
}
|
||||
|
||||
{
|
||||
const meta::number_type unsigned_type = meta::resolve_type<unsigned>();
|
||||
REQUIRE(unsigned_type);
|
||||
|
||||
CHECK(unsigned_type.get_flags().has(meta::number_flags::is_unsigned));
|
||||
CHECK(unsigned_type.get_size() == sizeof(unsigned));
|
||||
}
|
||||
}
|
||||
58
untests/meta_states/evalue_tests.cpp
Normal file
58
untests/meta_states/evalue_tests.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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().type == evalue.get_type());
|
||||
CHECK(evalue.get_index().name == "green");
|
||||
|
||||
CHECK(evalue.get_type() == meta::resolve_type<color>());
|
||||
CHECK(evalue.get_name() == "green");
|
||||
|
||||
CHECK(evalue.get_value() == color::green);
|
||||
}
|
||||
}
|
||||
107
untests/meta_states/function_tests.cpp
Normal file
107
untests/meta_states/function_tests.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
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().type == func.get_type());
|
||||
CHECK(func.get_index().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}).value() == ivec2{4,6});
|
||||
}
|
||||
|
||||
SUBCASE("ilength2") {
|
||||
const meta::function func = ivec2_type.get_function("ilength2");
|
||||
REQUIRE(func);
|
||||
|
||||
CHECK(func.get_index().type == func.get_type());
|
||||
CHECK(func.get_index().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}).value() == 13);
|
||||
}
|
||||
}
|
||||
81
untests/meta_states/member_tests.cpp
Normal file
81
untests/meta_states/member_tests.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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct clazz_1 {
|
||||
int int_member = 1;
|
||||
const int const_int_member = 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);
|
||||
|
||||
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;
|
||||
|
||||
CHECK(vm.get(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_NOTHROW(vm.set(v, 10)); CHECK(vm.get(v) == 10);
|
||||
CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 10);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
CHECK(vm.get(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_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::move(v), 12)); CHECK(vm.get(v) == 2);
|
||||
CHECK_THROWS(vm.set(std::move(std::as_const(v)), 13)); CHECK(vm.get(v) == 2);
|
||||
}
|
||||
}
|
||||
829
untests/meta_states/method_tests.cpp
Normal file
829
untests/meta_states/method_tests.cpp
Normal file
@@ -0,0 +1,829 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct clazz {
|
||||
clazz() = default;
|
||||
|
||||
clazz(clazz&&) = delete;
|
||||
clazz(const clazz&) = delete;
|
||||
|
||||
clazz& operator=(clazz&&) = delete;
|
||||
clazz& operator=(const clazz&) = delete;
|
||||
|
||||
//
|
||||
|
||||
int non_const_method() { return 1; }
|
||||
int non_const_method_noexcept() noexcept { return 2; }
|
||||
|
||||
int const_method() const { return 3; }
|
||||
int const_method_noexcept() const noexcept { return 4; }
|
||||
|
||||
int non_const_method_ref() & { return 5; }
|
||||
int non_const_method_noexcept_ref() & noexcept { return 6; }
|
||||
|
||||
int const_method_ref() const & { return 7; }
|
||||
int const_method_noexcept_ref() const & noexcept { return 8; }
|
||||
|
||||
int non_const_method_rref() && { return 9; }
|
||||
int non_const_method_noexcept_rref() && noexcept { return 10; }
|
||||
|
||||
int const_method_rref() const && { return 11; }
|
||||
int const_method_noexcept_rref() const && noexcept { return 12; }
|
||||
|
||||
//
|
||||
|
||||
int non_const_method_volatile() volatile { return 1; }
|
||||
int non_const_method_noexcept_volatile() volatile noexcept { return 2; }
|
||||
|
||||
int const_method_volatile() volatile const { return 3; }
|
||||
int const_method_noexcept_volatile() volatile const noexcept { return 4; }
|
||||
|
||||
int non_const_method_ref_volatile() volatile & { return 5; }
|
||||
int non_const_method_noexcept_ref_volatile() volatile & noexcept { return 6; }
|
||||
|
||||
int const_method_ref_volatile() volatile const & { return 7; }
|
||||
int const_method_noexcept_ref_volatile() volatile const & noexcept { return 8; }
|
||||
|
||||
int non_const_method_rref_volatile() volatile && { return 9; }
|
||||
int non_const_method_noexcept_rref_volatile() volatile && noexcept { return 10; }
|
||||
|
||||
int const_method_rref_volatile() volatile const && { return 11; }
|
||||
int const_method_noexcept_rref_volatile() volatile const && noexcept { return 12; }
|
||||
};
|
||||
|
||||
struct clazz2 {};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_states/method") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<clazz>()
|
||||
.method_("non_const_method", &clazz::non_const_method)
|
||||
.method_("non_const_method_noexcept", &clazz::non_const_method_noexcept)
|
||||
|
||||
.method_("const_method", &clazz::const_method)
|
||||
.method_("const_method_noexcept", &clazz::const_method_noexcept)
|
||||
|
||||
.method_("non_const_method_ref", &clazz::non_const_method_ref)
|
||||
.method_("non_const_method_noexcept_ref", &clazz::non_const_method_noexcept_ref)
|
||||
|
||||
.method_("const_method_ref", &clazz::const_method_ref)
|
||||
.method_("const_method_noexcept_ref", &clazz::const_method_noexcept_ref)
|
||||
|
||||
.method_("non_const_method_rref", &clazz::non_const_method_rref)
|
||||
.method_("non_const_method_noexcept_rref", &clazz::non_const_method_noexcept_rref)
|
||||
|
||||
.method_("const_method_rref", &clazz::const_method_rref)
|
||||
.method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref)
|
||||
|
||||
.method_("non_const_method_volatile", &clazz::non_const_method_volatile)
|
||||
.method_("non_const_method_noexcept_volatile", &clazz::non_const_method_noexcept_volatile)
|
||||
|
||||
.method_("const_method_volatile", &clazz::const_method_volatile)
|
||||
.method_("const_method_noexcept_volatile", &clazz::const_method_noexcept_volatile)
|
||||
|
||||
.method_("non_const_method_ref_volatile", &clazz::non_const_method_ref_volatile)
|
||||
.method_("non_const_method_noexcept_ref_volatile", &clazz::non_const_method_noexcept_ref_volatile)
|
||||
|
||||
.method_("const_method_ref_volatile", &clazz::const_method_ref_volatile)
|
||||
.method_("const_method_noexcept_ref_volatile", &clazz::const_method_noexcept_ref_volatile)
|
||||
|
||||
.method_("non_const_method_rref_volatile", &clazz::non_const_method_rref_volatile)
|
||||
.method_("non_const_method_noexcept_rref_volatile", &clazz::non_const_method_noexcept_rref_volatile)
|
||||
|
||||
.method_("const_method_rref_volatile", &clazz::const_method_rref_volatile)
|
||||
.method_("const_method_noexcept_rref_volatile", &clazz::const_method_noexcept_rref_volatile);
|
||||
|
||||
const meta::class_type ct = meta::resolve_type<clazz>();
|
||||
REQUIRE(ct);
|
||||
|
||||
SUBCASE("") {
|
||||
const meta::method method;
|
||||
CHECK_FALSE(method);
|
||||
CHECK_FALSE(method.is_valid());
|
||||
CHECK(method == ct.get_method("non-existent-method"));
|
||||
}
|
||||
|
||||
SUBCASE("operators") {
|
||||
const meta::method non_const_method_m = ct.get_method("non_const_method");
|
||||
const meta::method non_const_method_volatile_m = ct.get_method("non_const_method_volatile");
|
||||
CHECK(non_const_method_m == non_const_method_m);
|
||||
CHECK(non_const_method_m != non_const_method_volatile_m);
|
||||
CHECK((non_const_method_m < non_const_method_volatile_m || non_const_method_volatile_m < non_const_method_m));
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method") {
|
||||
const meta::method mi = ct.get_method("non_const_method");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method");
|
||||
CHECK(mi2.get_name() == "non_const_method_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == meta::method_flags{});
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == meta::method_flags::is_volatile);
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 1);
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 1);
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 1);
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 1);
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method_noexcept") {
|
||||
const meta::method mi = ct.get_method("non_const_method_noexcept");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_noexcept_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method_noexcept");
|
||||
CHECK(mi2.get_name() == "non_const_method_noexcept_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == meta::method_flags::is_noexcept);
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_noexcept | meta::method_flags::is_volatile));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 2);
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 2);
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 2);
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 2);
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method") {
|
||||
const meta::method mi = ct.get_method("const_method");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method");
|
||||
CHECK(mi2.get_name() == "const_method_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == meta::method_flags::is_const);
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_volatile));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 3);
|
||||
CHECK(mi.invoke(std::as_const(cl)).value() == 3);
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 3);
|
||||
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 3);
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 3);
|
||||
CHECK(mi2.invoke(std::as_const(cl)).value() == 3);
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 3);
|
||||
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 3);
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method_noexcept") {
|
||||
const meta::method mi = ct.get_method("const_method_noexcept");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_noexcept_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method_noexcept");
|
||||
CHECK(mi2.get_name() == "const_method_noexcept_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept | meta::method_flags::is_volatile));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 4);
|
||||
CHECK(mi.invoke(std::as_const(cl)).value() == 4);
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 4);
|
||||
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 4);
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 4);
|
||||
CHECK(mi2.invoke(std::as_const(cl)).value() == 4);
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 4);
|
||||
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 4);
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method_ref") {
|
||||
const meta::method mi = ct.get_method("non_const_method_ref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_ref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method_ref");
|
||||
CHECK(mi2.get_name() == "non_const_method_ref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == meta::method_flags::is_lvalue_qualified);
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_volatile | meta::method_flags::is_lvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 5);
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 5);
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_ref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_ref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method_noexcept_ref") {
|
||||
const meta::method mi = ct.get_method("non_const_method_noexcept_ref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_noexcept_ref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method_noexcept_ref");
|
||||
CHECK(mi2.get_name() == "non_const_method_noexcept_ref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_noexcept | meta::method_flags::is_lvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_noexcept | meta::method_flags::is_volatile | meta::method_flags::is_lvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 6);
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 6);
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref), const clazz&&>);
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_ref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method_ref") {
|
||||
const meta::method mi = ct.get_method("const_method_ref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_ref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method_ref");
|
||||
CHECK(mi2.get_name() == "const_method_ref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_lvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_volatile | meta::method_flags::is_lvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 7);
|
||||
CHECK(mi.invoke(std::as_const(cl)).value() == 7);
|
||||
CHECK_THROWS(mi.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 7);
|
||||
CHECK(mi2.invoke(std::as_const(cl)).value() == 7);
|
||||
CHECK_THROWS(mi2.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref), const clazz&>);
|
||||
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref), clazz&&>); // msvc issue
|
||||
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref), const clazz&&>); // msvc issue
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_ref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method_noexcept_ref") {
|
||||
const meta::method mi = ct.get_method("const_method_noexcept_ref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_noexcept_ref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method_noexcept_ref");
|
||||
CHECK(mi2.get_name() == "const_method_noexcept_ref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept | meta::method_flags::is_lvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept | meta::method_flags::is_volatile | meta::method_flags::is_lvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(mi.is_invocable_with<clazz&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK(mi2.is_invocable_with<clazz&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK(mi.invoke(cl).value() == 8);
|
||||
CHECK(mi.invoke(std::as_const(cl)).value() == 8);
|
||||
CHECK_THROWS(mi.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK(mi2.invoke(cl).value() == 8);
|
||||
CHECK(mi2.invoke(std::as_const(cl)).value() == 8);
|
||||
CHECK_THROWS(mi2.invoke(std::move(cl)));
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), const clazz&>);
|
||||
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), clazz&&>); // msvc issue
|
||||
//static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref), const clazz&&>); // msvc issue
|
||||
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), const clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_ref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method_rref") {
|
||||
const meta::method mi = ct.get_method("non_const_method_rref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_rref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method_rref");
|
||||
CHECK(mi2.get_name() == "non_const_method_rref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == meta::method_flags::is_rvalue_qualified);
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_volatile | meta::method_flags::is_rvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK_THROWS(mi.invoke(cl));
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 9);
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK_THROWS(mi2.invoke(cl));
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 9);
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_rref), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref), const clazz&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_rref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("non_const_method_noexcept_rref") {
|
||||
const meta::method mi = ct.get_method("non_const_method_noexcept_rref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("non_const_method_noexcept_rref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "non_const_method_noexcept_rref");
|
||||
CHECK(mi2.get_name() == "non_const_method_noexcept_rref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_noexcept | meta::method_flags::is_rvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_noexcept | meta::method_flags::is_volatile | meta::method_flags::is_rvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK_THROWS(mi.invoke(cl));
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 10);
|
||||
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
|
||||
|
||||
CHECK_THROWS(mi2.invoke(cl));
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 10);
|
||||
CHECK_THROWS(mi2.invoke(std::move(std::as_const(cl))));
|
||||
}
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref), const clazz&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), clazz&&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::non_const_method_noexcept_rref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method_rref") {
|
||||
const meta::method mi = ct.get_method("const_method_rref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_rref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method_rref");
|
||||
CHECK(mi2.get_name() == "const_method_rref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_rvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_volatile | meta::method_flags::is_rvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK_THROWS(mi.invoke(cl));
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 11);
|
||||
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 11);
|
||||
|
||||
CHECK_THROWS(mi2.invoke(cl));
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 11);
|
||||
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 11);
|
||||
}
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref), const clazz&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_rref_volatile), const clazz&&>);
|
||||
}
|
||||
|
||||
SUBCASE("const_method_noexcept_rref") {
|
||||
const meta::method mi = ct.get_method("const_method_noexcept_rref");
|
||||
REQUIRE(mi);
|
||||
|
||||
const meta::method mi2 = ct.get_method("const_method_noexcept_rref_volatile");
|
||||
REQUIRE(mi2);
|
||||
|
||||
CHECK(mi.get_name() == "const_method_noexcept_rref");
|
||||
CHECK(mi2.get_name() == "const_method_noexcept_rref_volatile");
|
||||
|
||||
{
|
||||
CHECK(mi.get_type().get_arity() == 0);
|
||||
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept | meta::method_flags::is_rvalue_qualified));
|
||||
|
||||
CHECK(mi2.get_type().get_arity() == 0);
|
||||
CHECK(mi2.get_type().get_owner_type() == meta::resolve_type<clazz>());
|
||||
CHECK(mi2.get_type().get_return_type() == meta::resolve_type<int>());
|
||||
CHECK(mi2.get_type().get_flags() == (meta::method_flags::is_const | meta::method_flags::is_noexcept | meta::method_flags::is_volatile | meta::method_flags::is_rvalue_qualified));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK_FALSE(mi.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi.is_invocable_with<const clazz&>());
|
||||
CHECK(mi.is_invocable_with<clazz&&>());
|
||||
CHECK(mi.is_invocable_with<const clazz&&>());
|
||||
|
||||
CHECK_FALSE(mi2.is_invocable_with<clazz&>());
|
||||
CHECK_FALSE(mi2.is_invocable_with<const clazz&>());
|
||||
CHECK(mi2.is_invocable_with<clazz&&>());
|
||||
CHECK(mi2.is_invocable_with<const clazz&&>());
|
||||
}
|
||||
|
||||
{
|
||||
clazz cl;
|
||||
|
||||
CHECK_THROWS(mi.invoke(cl));
|
||||
CHECK_THROWS(mi.invoke(std::as_const(cl)));
|
||||
CHECK(mi.invoke(std::move(cl)).value() == 12);
|
||||
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 12);
|
||||
|
||||
CHECK_THROWS(mi2.invoke(cl));
|
||||
CHECK_THROWS(mi2.invoke(std::as_const(cl)));
|
||||
CHECK(mi2.invoke(std::move(cl)).value() == 12);
|
||||
CHECK(mi2.invoke(std::move(std::as_const(cl))).value() == 12);
|
||||
}
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const clazz&&>);
|
||||
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), clazz&>);
|
||||
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), const clazz&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), clazz&&>);
|
||||
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref_volatile), const clazz&&>);
|
||||
}
|
||||
}
|
||||
114
untests/meta_states/scope_tests.cpp
Normal file
114
untests/meta_states/scope_tests.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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};
|
||||
}
|
||||
|
||||
ivec2 global_ivec2 = ivec2{1, 0};
|
||||
const ivec3 global_const_ivec3 = ivec3{1, 0};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_states/scope") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::scope_("meta/meta_states/scope/math")
|
||||
.enum_<color>("color")
|
||||
.class_<ivec2>("ivec2")
|
||||
.class_<ivec3>("ivec3")
|
||||
.function_("iadd2", &iadd2)
|
||||
.function_("iadd3", &iadd3)
|
||||
.variable_("global_ivec2", &global_ivec2)
|
||||
.variable_("global_const_ivec3", &global_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_classes().size() == 2);
|
||||
CHECK(math_scope.get_enums().size() == 1);
|
||||
CHECK(math_scope.get_functions().size() == 2);
|
||||
CHECK(math_scope.get_variables().size() == 2);
|
||||
|
||||
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_class("non-existent-class"));
|
||||
|
||||
const meta::class_type ivec2_type = math_scope.get_class("ivec2");
|
||||
REQUIRE(ivec2_type);
|
||||
|
||||
const meta::class_type ivec3_type = math_scope.get_class("ivec3");
|
||||
REQUIRE(ivec3_type);
|
||||
}
|
||||
|
||||
SUBCASE("enums") {
|
||||
CHECK_FALSE(math_scope.get_enum("non-existent-enum"));
|
||||
|
||||
const meta::enum_type color_type = math_scope.get_enum("color");
|
||||
REQUIRE(color_type);
|
||||
}
|
||||
|
||||
SUBCASE("functions") {
|
||||
CHECK_FALSE(math_scope.get_function("non-existent-function"));
|
||||
|
||||
const meta::function iadd2_func = math_scope.get_function("iadd2");
|
||||
REQUIRE(iadd2_func);
|
||||
|
||||
const meta::function iadd3_func = math_scope.get_function("iadd3");
|
||||
REQUIRE(iadd3_func);
|
||||
}
|
||||
|
||||
SUBCASE("variables") {
|
||||
CHECK_FALSE(math_scope.get_variable("non-existent-variable"));
|
||||
|
||||
const meta::variable global_ivec2_var = math_scope.get_variable("global_ivec2");
|
||||
REQUIRE(global_ivec2_var);
|
||||
CHECK(global_ivec2_var.get_type().get_data_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
const meta::variable global_const_ivec3_var = math_scope.get_variable("global_const_ivec3");
|
||||
REQUIRE(global_const_ivec3_var);
|
||||
CHECK(global_const_ivec3_var.get_type().get_data_type() == meta::resolve_type<ivec3>());
|
||||
}
|
||||
}
|
||||
100
untests/meta_states/variable_tests.cpp
Normal file
100
untests/meta_states/variable_tests.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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_NOTHROW(vm.set(10)); CHECK(vm.get() == 10);
|
||||
}
|
||||
|
||||
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_THROWS(vm.set(10)); CHECK(vm.get() == 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() == 10);
|
||||
|
||||
CHECK_NOTHROW(vm.set(20)); CHECK(vm.get() == 20);
|
||||
}
|
||||
|
||||
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_THROWS(vm.set(10)); CHECK(vm.get() == 2);
|
||||
}
|
||||
}
|
||||
41
untests/meta_types/array_type_tests.cpp
Normal file
41
untests/meta_types/array_type_tests.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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]>());
|
||||
}
|
||||
}
|
||||
465
untests/meta_types/class_type_tests.cpp
Normal file
465
untests/meta_types/class_type_tests.cpp
Normal file
@@ -0,0 +1,465 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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 final : base_clazz_1, base_clazz_2 {
|
||||
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;
|
||||
};
|
||||
|
||||
template < typename... Args >
|
||||
struct variadic_clazz {};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_types/class_type") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::class_<base_clazz_1>()
|
||||
.ctor_<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<int(int) const>(&base_clazz_1::base_method_1_overloaded))
|
||||
.method_("base_method_1_overloaded", meta::select<int(float) const>(&base_clazz_1::base_method_1_overloaded))
|
||||
.function_("base_function_1_overloaded", meta::select<int(int)>(&base_clazz_1::base_function_1_overloaded))
|
||||
.function_("base_function_1_overloaded", meta::select<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>()
|
||||
.ctor_<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>()
|
||||
.ctor_<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);
|
||||
|
||||
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 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::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));
|
||||
}
|
||||
|
||||
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() == std::vector<meta::any_type>{});
|
||||
}
|
||||
{
|
||||
const meta::class_type type = meta::resolve_type<variadic_clazz<int>>();
|
||||
REQUIRE(type);
|
||||
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<int>()});
|
||||
}
|
||||
{
|
||||
const meta::class_type type = meta::resolve_type<variadic_clazz<int, float>>();
|
||||
REQUIRE(type);
|
||||
CHECK(type.get_argument_types() == std::vector<meta::any_type>{meta::resolve_type<int>(), meta::resolve_type<float>()});
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("get_ctors") {
|
||||
CHECK(base_clazz_1_type.get_ctors().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_ctors().size() == 1);
|
||||
CHECK(derived_clazz_type.get_ctors().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});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_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_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));
|
||||
}
|
||||
}
|
||||
|
||||
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_ctor_with") {
|
||||
{
|
||||
CHECK_FALSE(base_clazz_1_type.get_ctor_with<>());
|
||||
CHECK(base_clazz_1_type.get_ctor_with<int>());
|
||||
CHECK_FALSE(base_clazz_1_type.get_ctor_with<float>());
|
||||
}
|
||||
{
|
||||
CHECK_FALSE(base_clazz_2_type.get_ctor_with<>());
|
||||
CHECK_FALSE(base_clazz_2_type.get_ctor_with<int>());
|
||||
CHECK(base_clazz_2_type.get_ctor_with<float>());
|
||||
}
|
||||
{
|
||||
CHECK_FALSE(derived_clazz_type.get_ctor_with<>());
|
||||
CHECK_FALSE(derived_clazz_type.get_ctor_with<int>());
|
||||
CHECK_FALSE(derived_clazz_type.get_ctor_with<float>());
|
||||
CHECK(derived_clazz_type.get_ctor_with<int, float>());
|
||||
CHECK_FALSE(derived_clazz_type.get_ctor_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", std::vector<meta::any_type>{int_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", std::vector<meta::any_type>{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", std::vector<meta::any_type>{float_type}));
|
||||
CHECK(base_clazz_1_type.get_function_with("base_function_1_overloaded", std::vector<meta::any_type>{int_type, int_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", std::vector<meta::any_type>{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", std::vector<meta::any_type>{double_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_function_with("base_function_1_overloaded", std::vector<meta::any_type>{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", std::vector<meta::any_type>{int_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", std::vector<meta::any_type>{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", std::vector<meta::any_type>{float_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", std::vector<meta::any_type>{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", std::vector<meta::any_type>{double_type}));
|
||||
CHECK_FALSE(base_clazz_1_type.get_method_with("base_method_1_overloaded", std::vector<meta::any_type>{double_type, double_type}));
|
||||
}
|
||||
}
|
||||
}
|
||||
98
untests/meta_types/enum_type_tests.cpp
Normal file
98
untests/meta_types/enum_type_tests.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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class color : unsigned {
|
||||
red = 0xFF0000,
|
||||
green = 0x00FF00,
|
||||
blue = 0x0000FF,
|
||||
white = red | green | 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);
|
||||
|
||||
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_underlying_type() == meta::resolve_type<unsigned>());
|
||||
|
||||
CHECK(color_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_underlying_type() == meta::resolve_type<unsigned>());
|
||||
|
||||
CHECK(color_type.get_evalues().size() == 4);
|
||||
}
|
||||
|
||||
SUBCASE("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);
|
||||
}
|
||||
|
||||
{
|
||||
const meta::evalue yellow_value = color_type.get_evalue("yellow");
|
||||
CHECK_FALSE(yellow_value);
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("value_to_name") {
|
||||
const meta::enum_type color_type = meta::resolve_type<color>();
|
||||
REQUIRE(color_type);
|
||||
|
||||
{
|
||||
REQUIRE(color_type.value_to_name(color::red));
|
||||
CHECK(color_type.value_to_name(color::red) == "red");
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
REQUIRE(color_type.value_to_name(meta::value{color::blue}));
|
||||
CHECK(color_type.value_to_name(color::blue) == "blue");
|
||||
}
|
||||
|
||||
{
|
||||
REQUIRE_FALSE(color_type.value_to_name(100500));
|
||||
REQUIRE_FALSE(color_type.value_to_name(color{100500}));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
68
untests/meta_types/function_type_tests.cpp
Normal file
68
untests/meta_types/function_type_tests.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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 {}
|
||||
}
|
||||
|
||||
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() == std::vector<meta::any_type>{meta::resolve_type<ivec2>()});
|
||||
|
||||
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2>());
|
||||
CHECK_FALSE(type.get_argument_type(1));
|
||||
}
|
||||
|
||||
SUBCASE("arg_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() == std::vector<meta::any_type>{meta::resolve_type<ivec2&>()});
|
||||
|
||||
CHECK(type.get_argument_type(0) == meta::resolve_type<ivec2&>());
|
||||
CHECK_FALSE(type.get_argument_type(1));
|
||||
}
|
||||
|
||||
SUBCASE("arg_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() == std::vector<meta::any_type>{meta::resolve_type<const ivec2&>()});
|
||||
|
||||
CHECK(type.get_argument_type(0) == meta::resolve_type<const ivec2&>());
|
||||
CHECK_FALSE(type.get_argument_type(1));
|
||||
}
|
||||
}
|
||||
47
untests/meta_types/member_type_tests.cpp
Normal file
47
untests/meta_types/member_type_tests.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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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{});
|
||||
|
||||
CHECK(type.get_owner_type() == meta::resolve_type<clazz_1>());
|
||||
CHECK(type.get_value_type() == meta::resolve_type<int>());
|
||||
}
|
||||
}
|
||||
68
untests/meta_types/method_type_tests.cpp
Normal file
68
untests/meta_types/method_type_tests.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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() == std::vector<meta::any_type>{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() == std::vector<meta::any_type>{});
|
||||
|
||||
CHECK_FALSE(type.get_argument_type(0));
|
||||
}
|
||||
}
|
||||
51
untests/meta_types/number_type_tests.cpp
Normal file
51
untests/meta_types/number_type_tests.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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_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_flags() == (
|
||||
meta::number_flags::is_signed |
|
||||
meta::number_flags::is_floating_point));
|
||||
}
|
||||
|
||||
SUBCASE("const unsigned") {
|
||||
const meta::number_type type = meta::resolve_type<const unsigned>();
|
||||
REQUIRE(type);
|
||||
|
||||
CHECK(type.get_size() == sizeof(unsigned));
|
||||
CHECK(type.get_flags() == (
|
||||
meta::number_flags::is_unsigned |
|
||||
meta::number_flags::is_integral));
|
||||
}
|
||||
}
|
||||
53
untests/meta_types/pointer_type_tests.cpp
Normal file
53
untests/meta_types/pointer_type_tests.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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_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_data_type() == meta::resolve_type<const 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_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_data_type() == meta::resolve_type<const int*>());
|
||||
}
|
||||
}
|
||||
61
untests/meta_types/reference_type_tests.cpp
Normal file
61
untests/meta_types/reference_type_tests.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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_flags() == (meta::reference_flags::is_lvalue));
|
||||
|
||||
CHECK(type.get_id() == meta::resolve_type<int&>().get_id());
|
||||
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_flags() == (meta::reference_flags::is_readonly | meta::reference_flags::is_lvalue));
|
||||
|
||||
CHECK(type.get_id() == meta::resolve_type<const int&>().get_id());
|
||||
CHECK(type.get_data_type() == meta::resolve_type<const int>());
|
||||
}
|
||||
|
||||
SUBCASE("int&&") {
|
||||
const meta::reference_type type = meta::resolve_type<int&&>();
|
||||
REQUIRE(type);
|
||||
|
||||
CHECK(type.get_flags() == (meta::reference_flags::is_rvalue));
|
||||
|
||||
CHECK(type.get_id() == meta::resolve_type<int&&>().get_id());
|
||||
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_flags() == (meta::reference_flags::is_readonly | meta::reference_flags::is_rvalue));
|
||||
|
||||
CHECK(type.get_id() == meta::resolve_type<const int&&>().get_id());
|
||||
CHECK(type.get_data_type() == meta::resolve_type<const int>());
|
||||
}
|
||||
}
|
||||
29
untests/meta_types/void_type_tests.cpp
Normal file
29
untests/meta_types/void_type_tests.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.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());
|
||||
CHECK(type.get_flags() == meta::void_flags{});
|
||||
}
|
||||
}
|
||||
1157
untests/meta_utilities/arg_tests.cpp
Normal file
1157
untests/meta_utilities/arg_tests.cpp
Normal file
File diff suppressed because it is too large
Load Diff
72
untests/meta_utilities/inst_tests.cpp
Normal file
72
untests/meta_utilities/inst_tests.cpp
Normal 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, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
[[maybe_unused]] ivec2() = default;
|
||||
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
|
||||
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
|
||||
|
||||
[[maybe_unused]] ivec2(ivec2&& other) noexcept {
|
||||
x = other.x;
|
||||
y = other.y;
|
||||
other.x = 0;
|
||||
other.y = 0;
|
||||
}
|
||||
|
||||
[[maybe_unused]] ivec2(const ivec2& other) noexcept {
|
||||
x = other.x;
|
||||
y = other.y;
|
||||
}
|
||||
|
||||
ivec2& operator=(ivec2&&) = delete;
|
||||
ivec2& operator=(const ivec2&) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("features/meta_utilities/inst") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
SUBCASE("ref") {
|
||||
ivec2 v{1,2};
|
||||
ivec2& vr = v;
|
||||
meta::detail::inst a{vr};
|
||||
|
||||
CHECK(a.get_raw_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(a.get_ref_type() == meta::detail::inst::ref_types::ref);
|
||||
}
|
||||
|
||||
SUBCASE("cref") {
|
||||
const ivec2 v{1,2};
|
||||
const ivec2& vr = v;
|
||||
meta::detail::inst a{vr};
|
||||
|
||||
CHECK(a.get_raw_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(a.get_ref_type() == meta::detail::inst::ref_types::cref);
|
||||
}
|
||||
|
||||
SUBCASE("rref") {
|
||||
ivec2 v{1,2};
|
||||
meta::detail::inst a{std::move(v)};
|
||||
|
||||
CHECK(a.get_raw_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(a.get_ref_type() == meta::detail::inst::ref_types::rref);
|
||||
}
|
||||
|
||||
SUBCASE("crref") {
|
||||
const ivec2 v{1,2};
|
||||
meta::detail::inst a{std::move(v)};
|
||||
|
||||
CHECK(a.get_raw_type() == meta::resolve_type<ivec2>());
|
||||
CHECK(a.get_ref_type() == meta::detail::inst::ref_types::crref);
|
||||
}
|
||||
}
|
||||
295
untests/meta_utilities/value_tests.cpp
Normal file
295
untests/meta_utilities/value_tests.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include "../meta_tests.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
[[maybe_unused]] ivec2() = default;
|
||||
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
|
||||
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
|
||||
|
||||
ivec2(ivec2&& other) noexcept
|
||||
: x{other.x}
|
||||
, y{other.y} {
|
||||
other.x = 0;
|
||||
other.y = 0;
|
||||
++move_ctor_counter;
|
||||
}
|
||||
|
||||
ivec2(const ivec2& other) noexcept
|
||||
: x{other.x}
|
||||
, y{other.y} {
|
||||
++copy_ctor_counter;
|
||||
}
|
||||
|
||||
ivec2& operator=(ivec2&& other) = delete;
|
||||
ivec2& operator=(const ivec2& other) = delete;
|
||||
public:
|
||||
static int move_ctor_counter;
|
||||
static int copy_ctor_counter;
|
||||
};
|
||||
|
||||
int ivec2::move_ctor_counter{0};
|
||||
int ivec2::copy_ctor_counter{0};
|
||||
|
||||
bool operator==(const ivec2& l, const ivec2& r) noexcept {
|
||||
return l.x == r.x && l.y == r.y;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_utilities/value") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
ivec2::move_ctor_counter = 0;
|
||||
ivec2::copy_ctor_counter = 0;
|
||||
|
||||
SUBCASE("cast types") {
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<meta::value&>().cast<ivec2>()),
|
||||
ivec2&>);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<meta::value&&>().cast<ivec2>()),
|
||||
ivec2&&>);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<const meta::value&>().cast<ivec2>()),
|
||||
const ivec2&>);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<const meta::value&&>().cast<ivec2>()),
|
||||
const ivec2&&>);
|
||||
}
|
||||
|
||||
SUBCASE("try_cast types") {
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<meta::value>().try_cast<ivec2>()),
|
||||
ivec2*>);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(std::declval<const meta::value>().try_cast<ivec2>()),
|
||||
const ivec2*>);
|
||||
}
|
||||
|
||||
SUBCASE("ivec2&") {
|
||||
ivec2 v{1,2};
|
||||
ivec2& vr = v;
|
||||
|
||||
meta::value val{vr};
|
||||
CHECK(ivec2::move_ctor_counter == 0);
|
||||
CHECK(ivec2::copy_ctor_counter == 1);
|
||||
|
||||
CHECK(val.get_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
CHECK(!std::memcmp(val.data(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(val.cdata(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(std::as_const(val).data(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(std::as_const(val).cdata(), &vr, sizeof(ivec2)));
|
||||
|
||||
CHECK(val == ivec2{1,2});
|
||||
CHECK(val == meta::value{ivec2{1,2}});
|
||||
|
||||
CHECK(val.cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
|
||||
}
|
||||
|
||||
SUBCASE("const ivec2&") {
|
||||
const ivec2 v{1,2};
|
||||
const ivec2& vr = v;
|
||||
|
||||
meta::value val{vr};
|
||||
CHECK(ivec2::move_ctor_counter == 0);
|
||||
CHECK(ivec2::copy_ctor_counter == 1);
|
||||
|
||||
CHECK(val.get_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
CHECK(!std::memcmp(val.data(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(val.cdata(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(std::as_const(val).data(), &vr, sizeof(ivec2)));
|
||||
CHECK(!std::memcmp(std::as_const(val).cdata(), &vr, sizeof(ivec2)));
|
||||
|
||||
CHECK(val == ivec2{1,2});
|
||||
CHECK(val == meta::value{ivec2{1,2}});
|
||||
|
||||
CHECK(val.cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
|
||||
}
|
||||
|
||||
SUBCASE("ivec2&&") {
|
||||
ivec2 v{1,2};
|
||||
|
||||
meta::value val{std::move(v)};
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
CHECK(val.get_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
CHECK(val == ivec2{1,2});
|
||||
CHECK(val == meta::value{ivec2{1,2}});
|
||||
|
||||
CHECK(val.cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
|
||||
}
|
||||
|
||||
SUBCASE("const ivec2&&") {
|
||||
const ivec2 v{1,2};
|
||||
|
||||
meta::value val{std::move(v)};
|
||||
CHECK(ivec2::move_ctor_counter == 0);
|
||||
CHECK(ivec2::copy_ctor_counter == 1);
|
||||
|
||||
CHECK(val.get_type() == meta::resolve_type<ivec2>());
|
||||
|
||||
CHECK(val == ivec2{1,2});
|
||||
CHECK(val == meta::value{ivec2{1,2}});
|
||||
|
||||
CHECK(val.cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(std::as_const(val).cast<ivec2>() == ivec2{1,2});
|
||||
|
||||
CHECK(*val.try_cast<ivec2>() == ivec2{1,2});
|
||||
CHECK(*std::as_const(val).try_cast<ivec2>() == ivec2{1,2});
|
||||
}
|
||||
|
||||
SUBCASE("value(value&&)") {
|
||||
ivec2 v{1,2};
|
||||
meta::value val_src{std::move(v)};
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
meta::value val_dst{std::move(val_src)};
|
||||
CHECK(val_dst == ivec2{1,2});
|
||||
CHECK(ivec2::move_ctor_counter == 2);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
CHECK(val_src == ivec2{0,0});
|
||||
CHECK(val_src.data() != val_dst.data());
|
||||
}
|
||||
|
||||
SUBCASE("value(const meta::value&)") {
|
||||
const ivec2 v{1,2};
|
||||
meta::value val_src{v};
|
||||
CHECK(ivec2::move_ctor_counter == 0);
|
||||
CHECK(ivec2::copy_ctor_counter == 1);
|
||||
|
||||
meta::value val_dst{val_src};
|
||||
CHECK(val_dst == ivec2{1,2});
|
||||
CHECK(ivec2::move_ctor_counter == 0);
|
||||
CHECK(ivec2::copy_ctor_counter == 2);
|
||||
|
||||
CHECK(val_src == ivec2{1,2});
|
||||
CHECK(val_src.data() != val_dst.data());
|
||||
}
|
||||
|
||||
SUBCASE("value& operator=(value&&)") {
|
||||
meta::value val_src1{std::string("world")};
|
||||
meta::value val_src2{ivec2{1,2}};
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
meta::value val_dst{std::string("hello")};
|
||||
|
||||
val_dst = std::move(val_src1);
|
||||
CHECK(val_dst == std::string("world"));
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
val_dst = std::move(val_src2);
|
||||
CHECK(val_dst == ivec2{1,2});
|
||||
CHECK(ivec2::move_ctor_counter == 2);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
CHECK(val_src2 == ivec2{0,0});
|
||||
CHECK(val_src2.data() != val_dst.data());
|
||||
}
|
||||
|
||||
SUBCASE("value& operator=(const meta::value&)") {
|
||||
meta::value val_src1{std::string("world")};
|
||||
meta::value val_src2{ivec2{1,2}};
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
meta::value val_dst{std::string("hello")};
|
||||
|
||||
val_dst = val_src1;
|
||||
CHECK(val_dst == std::string("world"));
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
val_dst = val_src2;
|
||||
CHECK(val_dst == ivec2{1,2});
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 1);
|
||||
|
||||
CHECK(val_src2 == ivec2{1,2});
|
||||
CHECK(val_src2.data() != val_dst.data());
|
||||
}
|
||||
|
||||
SUBCASE("swap") {
|
||||
meta::value val1{std::string("world")};
|
||||
meta::value val2{ivec2{1,2}};
|
||||
CHECK(ivec2::move_ctor_counter == 1);
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
val1.swap(val2);
|
||||
CHECK(val1 == ivec2{1,2});
|
||||
CHECK(val2 == std::string("world"));
|
||||
CHECK((ivec2::move_ctor_counter == 2 || ivec2::move_ctor_counter == 3));
|
||||
CHECK(ivec2::copy_ctor_counter == 0);
|
||||
|
||||
swap(val1, val2);
|
||||
CHECK(val1 == std::string("world"));
|
||||
CHECK(val2 == ivec2{1,2});
|
||||
}
|
||||
|
||||
SUBCASE("ostream") {
|
||||
std::stringstream str_stream;
|
||||
CHECK_NOTHROW(str_stream << meta::value{21} << " " << meta::value{42});
|
||||
CHECK_THROWS((str_stream << meta::value{ivec2{1,2}}));
|
||||
REQUIRE(str_stream.str() == "21 42");
|
||||
}
|
||||
|
||||
SUBCASE("istream") {
|
||||
std::stringstream str_stream{"21 42"};
|
||||
|
||||
meta::value v{ivec2{1,2}};
|
||||
CHECK_THROWS(str_stream >> v);
|
||||
|
||||
v = meta::value{0};
|
||||
CHECK_NOTHROW(str_stream >> v);
|
||||
CHECK(v == 21);
|
||||
CHECK_NOTHROW(str_stream >> v);
|
||||
CHECK(v == 42);
|
||||
}
|
||||
|
||||
SUBCASE("operator==") {
|
||||
CHECK(meta::value{ivec2{1,2}} == ivec2{1,2});
|
||||
CHECK_FALSE(meta::value{ivec2{1,2}} == ivec2{1,3});
|
||||
|
||||
CHECK(ivec2{1,2} == meta::value{ivec2{1,2}});
|
||||
CHECK_FALSE(ivec2{1,3} == meta::value{ivec2{1,2}});
|
||||
|
||||
CHECK(meta::value{ivec2{1,2}} == meta::value{ivec2{1,2}});
|
||||
CHECK_FALSE(meta::value{ivec2{1,2}} == meta::value{ivec2{1,3}});
|
||||
|
||||
{
|
||||
class empty_class1 {};
|
||||
class empty_class2 {};
|
||||
|
||||
CHECK_FALSE(operator==(meta::value{empty_class1{}}, meta::value{empty_class2{}}));
|
||||
CHECK_THROWS(operator==(meta::value{empty_class1{}}, meta::value{empty_class1{}}));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user