mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
Merge branch 'feature/ctor_infos' into dev
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
#include "meta_class.hpp"
|
||||
#include "meta_class_info.hpp"
|
||||
|
||||
#include "meta_ctor.hpp"
|
||||
#include "meta_ctor_info.hpp"
|
||||
|
||||
#include "meta_data.hpp"
|
||||
#include "meta_data_info.hpp"
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "meta_fwd.hpp"
|
||||
|
||||
#include "meta_ctor.hpp"
|
||||
#include "meta_data.hpp"
|
||||
#include "meta_field.hpp"
|
||||
#include "meta_function.hpp"
|
||||
@@ -40,6 +41,12 @@ namespace meta_hpp
|
||||
detail::merge_with(info_.classes_, info.id(), info, &class_info::merge);
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
void add_(ctor_<Args...> internal) {
|
||||
ctor_info info = std::move(internal).template make_info<Class>();
|
||||
detail::merge_with(info_.ctors_, info.family(), info, &ctor_info::merge);
|
||||
}
|
||||
|
||||
void add_(data_ internal) {
|
||||
data_info info = std::move(internal).make_info();
|
||||
detail::merge_with(info_.datas_, info.id(), info, &data_info::merge);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "meta_fwd.hpp"
|
||||
#include "meta_value.hpp"
|
||||
|
||||
#include "meta_ctor_info.hpp"
|
||||
#include "meta_data_info.hpp"
|
||||
#include "meta_field_info.hpp"
|
||||
#include "meta_function_info.hpp"
|
||||
@@ -42,6 +43,13 @@ namespace meta_hpp
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void each_ctor(F&& f) const {
|
||||
for ( auto&& family_info : ctors_ ) {
|
||||
std::invoke(f, family_info.second);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void each_data(F&& f) const {
|
||||
for ( auto&& id_info : datas_ ) {
|
||||
@@ -80,6 +88,7 @@ namespace meta_hpp
|
||||
template < typename F >
|
||||
void visit(F&& f) const {
|
||||
each_class(f);
|
||||
each_ctor(f);
|
||||
each_data(f);
|
||||
each_field(f);
|
||||
each_function(f);
|
||||
@@ -91,6 +100,16 @@ namespace meta_hpp
|
||||
return detail::find_opt(classes_, id);
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
std::optional<ctor_info> get_ctor() const {
|
||||
for ( auto&& family_info : ctors_ ) {
|
||||
if ( family_info.second.is_invocable<Args...>() ) {
|
||||
return family_info.second;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<data_info> get_data(std::string_view id) const {
|
||||
return detail::find_opt(datas_, id);
|
||||
}
|
||||
@@ -116,6 +135,7 @@ namespace meta_hpp
|
||||
throw std::logic_error("class_info::merge failed");
|
||||
}
|
||||
detail::merge_with(classes_, other.classes_, &class_info::merge);
|
||||
detail::merge_with(ctors_, other.ctors_, &ctor_info::merge);
|
||||
detail::merge_with(datas_, other.datas_, &data_info::merge);
|
||||
detail::merge_with(fields_, other.fields_, &field_info::merge);
|
||||
detail::merge_with(functions_, other.functions_, &function_info::merge);
|
||||
@@ -134,6 +154,7 @@ namespace meta_hpp
|
||||
std::string id_;
|
||||
family_id family_;
|
||||
std::map<std::string, class_info, std::less<>> classes_;
|
||||
std::map<family_id, ctor_info, std::less<>> ctors_;
|
||||
std::map<std::string, data_info, std::less<>> datas_;
|
||||
std::map<std::string, field_info, std::less<>> fields_;
|
||||
std::map<std::string, function_info, std::less<>> functions_;
|
||||
|
||||
43
headers/meta.hpp/meta_ctor.hpp
Normal file
43
headers/meta.hpp/meta_ctor.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* 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_fwd.hpp"
|
||||
|
||||
#include "meta_data.hpp"
|
||||
|
||||
#include "meta_ctor_info.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename... Args >
|
||||
class ctor_ {
|
||||
public:
|
||||
ctor_() = default;
|
||||
|
||||
template < typename Class >
|
||||
ctor_info make_info() const {
|
||||
static_assert(std::is_constructible_v<Class, Args...>);
|
||||
ctor_info info{detail::typename_arg<Class>, detail::typename_args<Args...>};
|
||||
detail::merge_with(info.datas_, datas_, &data_info::merge);
|
||||
return info;
|
||||
}
|
||||
|
||||
template < typename... Internals >
|
||||
ctor_& operator()(Internals&&...internals) {
|
||||
(add_(std::forward<Internals>(internals)), ...);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
void add_(data_ internal) {
|
||||
data_info info = std::move(internal).make_info();
|
||||
detail::merge_with(datas_, info.id(), info, &data_info::merge);
|
||||
}
|
||||
private:
|
||||
std::map<std::string, data_info, std::less<>> datas_;
|
||||
};
|
||||
}
|
||||
188
headers/meta.hpp/meta_ctor_info.hpp
Normal file
188
headers/meta.hpp/meta_ctor_info.hpp
Normal file
@@ -0,0 +1,188 @@
|
||||
/*******************************************************************************
|
||||
* 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_fwd.hpp"
|
||||
|
||||
#include "meta_value.hpp"
|
||||
|
||||
#include "meta_data_info.hpp"
|
||||
|
||||
namespace meta_hpp::ctor_detail
|
||||
{
|
||||
template < typename Class, typename... Args, std::size_t... Is >
|
||||
value raw_invoke_impl(
|
||||
value* args,
|
||||
std::index_sequence<Is...>)
|
||||
{
|
||||
using ct = detail::ctor_traits<Class, Args...>;
|
||||
using return_type = typename ct::return_type;
|
||||
using argument_types = typename ct::argument_types;
|
||||
|
||||
[[maybe_unused]] auto typed_arguments = std::make_tuple(
|
||||
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
|
||||
|
||||
if ( !(std::get<Is>(typed_arguments) && ...) ) {
|
||||
throw std::logic_error("an attempt to call a ctor with incorrect argument types");
|
||||
}
|
||||
|
||||
return_type return_value{std::move(*std::get<Is>(typed_arguments))...};
|
||||
return value{std::move(return_value)};
|
||||
}
|
||||
|
||||
template < typename Class, typename... Args >
|
||||
value raw_invoke(
|
||||
value* args,
|
||||
std::size_t arg_count)
|
||||
{
|
||||
using ct = detail::ctor_traits<Class, Args...>;
|
||||
|
||||
if ( arg_count != ct::arity ) {
|
||||
throw std::logic_error("an attempt to call a ctor with an incorrect arity");
|
||||
}
|
||||
|
||||
return raw_invoke_impl<Class, Args...>(args, std::make_index_sequence<ct::arity>());
|
||||
}
|
||||
|
||||
using ctor_invoke = std::function<value(value*, std::size_t)>;
|
||||
|
||||
template < typename Class, typename... Args >
|
||||
ctor_invoke make_invoke() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_invoke<Class, Args...>, _1, _2);
|
||||
}
|
||||
|
||||
template < typename Class, typename... Args >
|
||||
family_id make_return_type() {
|
||||
using ct = detail::ctor_traits<Class, Args...>;
|
||||
using return_type = typename ct::return_type;
|
||||
return get_family_id<return_type>();
|
||||
}
|
||||
|
||||
template < typename Class, typename... Args, std::size_t... Is >
|
||||
std::vector<family_id> make_argument_types_impl(std::index_sequence<Is...>) {
|
||||
using ct = detail::ctor_traits<Class, Args...>;
|
||||
using argument_types = typename ct::argument_types;
|
||||
return { get_family_id<std::tuple_element_t<Is, argument_types>>()... };
|
||||
}
|
||||
|
||||
template < typename Class, typename... Args >
|
||||
std::vector<family_id> make_argument_types() {
|
||||
using ct = detail::ctor_traits<Class, Args...>;
|
||||
return make_argument_types_impl<Class, Args...>(std::make_index_sequence<ct::arity>());
|
||||
}
|
||||
|
||||
template < typename... Args, std::size_t... Is >
|
||||
bool parameters_equal(const std::vector<family_id>& parameters, std::index_sequence<Is...>) {
|
||||
if ( parameters.size() != sizeof...(Args) ) {
|
||||
return false;
|
||||
}
|
||||
return ((get_family_id<std::tuple_element_t<Is, std::tuple<Args...>>>() == parameters[Is]) && ... );
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
bool parameters_equal(const std::vector<family_id>& parameters) {
|
||||
return parameters_equal<Args...>(parameters, std::make_index_sequence<sizeof...(Args)>());
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class ctor_info {
|
||||
public:
|
||||
ctor_info() = delete;
|
||||
|
||||
ctor_info(ctor_info&&) = default;
|
||||
ctor_info(const ctor_info&) = default;
|
||||
|
||||
ctor_info& operator=(ctor_info&&) = default;
|
||||
ctor_info& operator=(const ctor_info&) = default;
|
||||
public:
|
||||
family_id family() const noexcept {
|
||||
return family_;
|
||||
}
|
||||
|
||||
std::size_t arity() const noexcept {
|
||||
return argument_types_.size();
|
||||
}
|
||||
|
||||
family_id return_type() const noexcept {
|
||||
return return_type_;
|
||||
}
|
||||
|
||||
std::optional<family_id> argument_type(std::size_t index) const noexcept {
|
||||
if ( index < argument_types_.size() ) {
|
||||
return argument_types_[index];
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
value invoke(Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0u ) {
|
||||
std::array<value, sizeof...(Args)> vargs{std::forward<Args>(args)...};
|
||||
return invoke_(vargs.data(), vargs.size());
|
||||
} else {
|
||||
return invoke_(nullptr, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename R, typename Rp = std::decay_t<R>, typename... Args >
|
||||
Rp invoke_r(Args&&... args) const {
|
||||
return invoke(std::forward<Args>(args)...).template cast<Rp>();
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
value operator()(Args&&... args) const {
|
||||
return invoke(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
bool is_invocable() const noexcept {
|
||||
return ctor_detail::parameters_equal<Args...>(argument_types_);
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void each_data(F&& f) const {
|
||||
for ( auto&& id_info : datas_ ) {
|
||||
std::invoke(f, id_info.second);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void visit(F&& f) const {
|
||||
each_data(f);
|
||||
}
|
||||
|
||||
std::optional<data_info> get_data(std::string_view id) const {
|
||||
return detail::find_opt(datas_, id);
|
||||
}
|
||||
|
||||
void merge(const ctor_info& other) {
|
||||
if ( family() != other.family() ) {
|
||||
throw std::logic_error("ctor_info::merge failed");
|
||||
}
|
||||
detail::merge_with(datas_, other.datas_, &data_info::merge);
|
||||
}
|
||||
private:
|
||||
template < typename... Args >
|
||||
friend class ctor_;
|
||||
|
||||
template < typename Class, typename... Args >
|
||||
ctor_info(detail::typename_arg_t<Class>, detail::typename_args_t<Args...>)
|
||||
: family_{get_family_id<detail::ctor_traits<Class, Args...>>()}
|
||||
, return_type_{ctor_detail::make_return_type<Class, Args...>()}
|
||||
, argument_types_{ctor_detail::make_argument_types<Class, Args...>()}
|
||||
, invoke_{ctor_detail::make_invoke<Class, Args...>()} {}
|
||||
private:
|
||||
family_id family_;
|
||||
family_id return_type_;
|
||||
std::vector<family_id> argument_types_;
|
||||
ctor_detail::ctor_invoke invoke_;
|
||||
std::map<std::string, data_info, std::less<>> datas_;
|
||||
};
|
||||
}
|
||||
@@ -122,9 +122,23 @@ namespace meta_hpp
|
||||
return getter_(instance);
|
||||
}
|
||||
|
||||
template < typename R, typename Rp = std::decay_t<R> >
|
||||
Rp get_r(cinstance instance) const {
|
||||
return get(instance).template cast<Rp>();
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
void set(instance instance, Value&& value) const {
|
||||
return setter_(instance, std::forward<Value>(value));
|
||||
setter_(instance, std::forward<Value>(value));
|
||||
}
|
||||
|
||||
value operator()(cinstance instance) const {
|
||||
return get(instance);
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
void operator()(instance instance, Value&& value) const {
|
||||
set(instance, std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
|
||||
@@ -134,6 +134,19 @@ namespace meta_hpp
|
||||
}
|
||||
}
|
||||
|
||||
template < typename R, typename Rp = std::decay_t<R>, typename... Args >
|
||||
std::optional<Rp> invoke_r(Args&&... args) const {
|
||||
if ( std::optional<value> r = invoke(std::forward<Args>(args)...) ) {
|
||||
return std::move(r)->template cast<Rp>();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
std::optional<value> operator()(Args&&... args) const {
|
||||
return invoke(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void each_data(F&& f) const {
|
||||
for ( auto&& id_info : datas_ ) {
|
||||
|
||||
@@ -105,8 +105,15 @@ namespace meta_hpp::detail
|
||||
struct typename_arg_t {
|
||||
};
|
||||
|
||||
template < typename... Args >
|
||||
struct typename_args_t {
|
||||
};
|
||||
|
||||
template < typename Arg >
|
||||
inline typename_arg_t<Arg> typename_arg;
|
||||
|
||||
template < typename... Args >
|
||||
inline typename_args_t<Args...> typename_args;
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
@@ -136,6 +143,16 @@ namespace meta_hpp::detail
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename Class, typename... Args >
|
||||
struct ctor_traits {
|
||||
static constexpr std::size_t arity = sizeof...(Args);
|
||||
using return_type = std::decay_t<Class>;
|
||||
using argument_types = std::tuple<std::decay_t<Args>...>;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename Field >
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace meta_hpp
|
||||
std::add_pointer_t<T>
|
||||
try_cast() noexcept {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
return fid() == get_family_id<T>()
|
||||
return fid_ == get_family_id<T>()
|
||||
? static_cast<std::add_pointer_t<T>>(data_)
|
||||
: nullptr;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ namespace meta_hpp
|
||||
std::add_pointer_t<std::add_const_t<T>>
|
||||
try_cast() const noexcept {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
return fid() == get_family_id<T>()
|
||||
return fid_ == get_family_id<T>()
|
||||
? static_cast<std::add_pointer_t<std::add_const_t<T>>>(data_)
|
||||
: nullptr;
|
||||
}
|
||||
@@ -91,8 +91,8 @@ namespace meta_hpp
|
||||
, typename = std::enable_if_t<!std::is_same_v<T, value>>
|
||||
, typename = std::enable_if_t<!std::is_same_v<T, instance>>
|
||||
, typename = std::enable_if_t<!std::is_same_v<T, cinstance>> >
|
||||
cinstance(const T& data)
|
||||
: data_{std::addressof(data)}
|
||||
cinstance(const T& v)
|
||||
: data_{std::addressof(v)}
|
||||
, fid_{get_family_id<T>()} {}
|
||||
|
||||
cinstance(const value& v)
|
||||
@@ -115,7 +115,7 @@ namespace meta_hpp
|
||||
std::add_pointer_t<std::add_const_t<T>>
|
||||
try_cast() const noexcept {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
return fid() == get_family_id<T>()
|
||||
return fid_ == get_family_id<T>()
|
||||
? static_cast<std::add_pointer_t<std::add_const_t<T>>>(data_)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
@@ -208,20 +208,31 @@ namespace meta_hpp
|
||||
std::optional<value> invoke(T& inst, Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0u ) {
|
||||
std::array<value, sizeof...(Args)> vargs{std::forward<Args>(args)...};
|
||||
return invoke_(inst, vargs.data(), vargs.size());
|
||||
if constexpr ( std::is_const_v<T> ) {
|
||||
return cinvoke_(inst, vargs.data(), vargs.size());
|
||||
} else {
|
||||
return invoke_(inst, vargs.data(), vargs.size());
|
||||
}
|
||||
} else {
|
||||
return invoke_(inst, nullptr, 0u);
|
||||
if constexpr ( std::is_const_v<T> ) {
|
||||
return cinvoke_(inst, nullptr, 0u);
|
||||
} else {
|
||||
return invoke_(inst, nullptr, 0u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T, typename... Args >
|
||||
std::optional<value> invoke(const T& inst, Args&&... args) const {
|
||||
if constexpr ( sizeof...(Args) > 0u ) {
|
||||
std::array<value, sizeof...(Args)> vargs{std::forward<Args>(args)...};
|
||||
return cinvoke_(inst, vargs.data(), vargs.size());
|
||||
} else {
|
||||
return cinvoke_(inst, nullptr, 0u);
|
||||
template < typename R, typename Rp = std::decay_t<R>, typename T, typename... Args >
|
||||
std::optional<Rp> invoke_r(T& inst, Args&&... args) const {
|
||||
if ( std::optional<value> r = invoke(inst, std::forward<Args>(args)...) ) {
|
||||
return std::move(r)->template cast<Rp>();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template < typename T, typename... Args >
|
||||
std::optional<value> operator()(T& inst, Args&&... args) const {
|
||||
return invoke(inst, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "meta_type.hpp"
|
||||
|
||||
#include "meta_class.hpp"
|
||||
#include "meta_ctor.hpp"
|
||||
#include "meta_data.hpp"
|
||||
#include "meta_field.hpp"
|
||||
#include "meta_function.hpp"
|
||||
#include "meta_method.hpp"
|
||||
@@ -150,6 +152,7 @@ namespace meta_hpp
|
||||
detail::merge_with(classes_, name, info, &class_info::merge);
|
||||
|
||||
info.visit(overloaded {
|
||||
[](const ctor_info&) {},
|
||||
[](const data_info&) {},
|
||||
[this, &name](const auto& internal){
|
||||
add_(name, internal);
|
||||
|
||||
@@ -53,33 +53,36 @@ namespace meta_hpp
|
||||
value& operator=(value&&) = default;
|
||||
value& operator=(const value&) = default;
|
||||
|
||||
template < typename T
|
||||
, typename U = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<U, value>> >
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<Tp, value>> >
|
||||
value(T&& val)
|
||||
: raw_{std::forward<T>(val)}
|
||||
, fid_{get_family_id<U>()}
|
||||
, traits_{value_detail::get_traits<U>()} {}
|
||||
, fid_{get_family_id<Tp>()}
|
||||
, traits_{value_detail::get_traits<Tp>()} {}
|
||||
|
||||
template < typename T
|
||||
, typename U = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<U, value>> >
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<Tp, value>> >
|
||||
value& operator=(T&& val) {
|
||||
value{std::forward<T>(val)}.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename T, typename... Args >
|
||||
template < typename T, typename Tp = std::decay_t<T>, typename... Args >
|
||||
explicit value(std::in_place_type_t<T>, Args&&... args)
|
||||
: raw_{std::in_place_type<T>, std::forward<Args>(args)...}
|
||||
, fid_{get_family_id<T>()}
|
||||
, traits_{value_detail::get_traits<T>()} {}
|
||||
: raw_{std::in_place_type<Tp>, std::forward<Args>(args)...}
|
||||
, fid_{get_family_id<Tp>()}
|
||||
, traits_{value_detail::get_traits<Tp>()} {}
|
||||
|
||||
template < typename T, typename U, typename... Args >
|
||||
explicit value(std::in_place_type_t<T>, std::initializer_list<U> ilist, Args&&... args)
|
||||
: raw_{std::in_place_type<T>, ilist, std::forward<Args>(args)...}
|
||||
, fid_{get_family_id<T>()}
|
||||
, traits_{value_detail::get_traits<T>()} {}
|
||||
template < typename T, typename Tp = std::decay_t<T>, typename I, typename... Args >
|
||||
explicit value(std::in_place_type_t<T>, std::initializer_list<I> ilist, Args&&... args)
|
||||
: raw_{std::in_place_type<Tp>, ilist, std::forward<Args>(args)...}
|
||||
, fid_{get_family_id<Tp>()}
|
||||
, traits_{value_detail::get_traits<Tp>()} {}
|
||||
|
||||
template < typename T >
|
||||
bool has_type() const noexcept {
|
||||
return fid_ == get_family_id<T>();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T cast() && {
|
||||
@@ -129,12 +132,11 @@ namespace meta_hpp
|
||||
swap(traits_, other.traits_);
|
||||
}
|
||||
|
||||
template < typename T
|
||||
, typename U = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<U, value>> >
|
||||
template < typename T, typename Tp = std::decay_t<T>
|
||||
, typename = std::enable_if_t<!std::is_same_v<Tp, value>> >
|
||||
bool equals(T&& other) const {
|
||||
return fid() == get_family_id<U>()
|
||||
&& std::equal_to<>{}(*try_cast<U>(), std::forward<T>(other));
|
||||
return fid_ == get_family_id<Tp>()
|
||||
&& std::equal_to<>{}(*try_cast<Tp>(), std::forward<T>(other));
|
||||
}
|
||||
|
||||
bool equals(const value& other) const {
|
||||
@@ -146,7 +148,7 @@ namespace meta_hpp
|
||||
unsigned to_uint() const { return cast<unsigned>(); }
|
||||
float to_float() const { return cast<float>(); }
|
||||
double to_double() const { return cast<double>(); }
|
||||
std::string to_string() const { return cast<std::string>(); }
|
||||
const std::string& to_string() const { return cast<const std::string&>(); }
|
||||
|
||||
std::int8_t to_int8() const { return cast<std::int8_t>(); }
|
||||
std::int16_t to_int16() const { return cast<std::int16_t>(); }
|
||||
@@ -162,26 +164,26 @@ namespace meta_hpp
|
||||
std::size_t to_size_t() const { return cast<std::size_t>(); }
|
||||
std::uintptr_t to_uintptr_t() const { return cast<std::uintptr_t>(); }
|
||||
public:
|
||||
bool is_bool() const noexcept { return !!try_cast<bool>(); }
|
||||
bool is_int() const noexcept { return !!try_cast<int>(); }
|
||||
bool is_uint() const noexcept { return !!try_cast<unsigned>(); }
|
||||
bool is_float() const noexcept { return !!try_cast<float>(); }
|
||||
bool is_double() const noexcept { return !!try_cast<double>(); }
|
||||
bool is_string() const noexcept { return !!try_cast<std::string>(); }
|
||||
bool is_bool() const noexcept { return has_type<bool>(); }
|
||||
bool is_int() const noexcept { return has_type<int>(); }
|
||||
bool is_uint() const noexcept { return has_type<unsigned>(); }
|
||||
bool is_float() const noexcept { return has_type<float>(); }
|
||||
bool is_double() const noexcept { return has_type<double>(); }
|
||||
bool is_string() const noexcept { return has_type<std::string>(); }
|
||||
|
||||
bool is_int8() const noexcept { return !!try_cast<std::int8_t>(); }
|
||||
bool is_int16() const noexcept { return !!try_cast<std::int16_t>(); }
|
||||
bool is_int32() const noexcept { return !!try_cast<std::int32_t>(); }
|
||||
bool is_int64() const noexcept { return !!try_cast<std::int64_t>(); }
|
||||
bool is_ptrdiff_t() const noexcept { return !!try_cast<std::ptrdiff_t>(); }
|
||||
bool is_intptr_t() const noexcept { return !!try_cast<std::intptr_t>(); }
|
||||
bool is_int8() const noexcept { return has_type<std::int8_t>(); }
|
||||
bool is_int16() const noexcept { return has_type<std::int16_t>(); }
|
||||
bool is_int32() const noexcept { return has_type<std::int32_t>(); }
|
||||
bool is_int64() const noexcept { return has_type<std::int64_t>(); }
|
||||
bool is_ptrdiff_t() const noexcept { return has_type<std::ptrdiff_t>(); }
|
||||
bool is_intptr_t() const noexcept { return has_type<std::intptr_t>(); }
|
||||
|
||||
bool is_uint8() const noexcept { return !!try_cast<std::uint8_t>(); }
|
||||
bool is_uint16() const noexcept { return !!try_cast<std::uint16_t>(); }
|
||||
bool is_uint32() const noexcept { return !!try_cast<std::uint32_t>(); }
|
||||
bool is_uint64() const noexcept { return !!try_cast<std::uint64_t>(); }
|
||||
bool is_size_t() const noexcept { return !!try_cast<std::size_t>(); }
|
||||
bool is_uintptr_t() const noexcept { return !!try_cast<std::uintptr_t>(); }
|
||||
bool is_uint8() const noexcept { return has_type<std::uint8_t>(); }
|
||||
bool is_uint16() const noexcept { return has_type<std::uint16_t>(); }
|
||||
bool is_uint32() const noexcept { return has_type<std::uint32_t>(); }
|
||||
bool is_uint64() const noexcept { return has_type<std::uint64_t>(); }
|
||||
bool is_size_t() const noexcept { return has_type<std::size_t>(); }
|
||||
bool is_uintptr_t() const noexcept { return has_type<std::uintptr_t>(); }
|
||||
private:
|
||||
std::any raw_;
|
||||
family_id fid_;
|
||||
@@ -213,7 +215,7 @@ namespace meta_hpp::value_detail
|
||||
if constexpr ( std::is_invocable_v<std::equal_to<>, T, T> ) {
|
||||
return std::equal_to<>{}(*l.try_cast<T>(), *r.try_cast<T>());
|
||||
} else {
|
||||
return std::addressof(l) == std::addressof(r);
|
||||
return value_cdata<T>(l) == value_cdata<T>(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +96,25 @@ namespace meta_hpp
|
||||
return getter_();
|
||||
}
|
||||
|
||||
template < typename R, typename Rp = std::decay_t<R> >
|
||||
Rp get_r() const {
|
||||
return get().template cast<Rp>();
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
void set(Value&& value) const {
|
||||
return setter_(std::forward<Value>(value));
|
||||
}
|
||||
|
||||
value operator()() const {
|
||||
return get();
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
void operator()(Value&& value) const {
|
||||
return set(std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void each_data(F&& f) const {
|
||||
for ( auto&& id_info : datas_ ) {
|
||||
|
||||
138
untests/meta_ctor_tests.cpp
Normal file
138
untests/meta_ctor_tests.cpp
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)
|
||||
******************************************************************************/
|
||||
|
||||
#include <meta.hpp/meta_class.hpp>
|
||||
#include <meta.hpp/meta_ctor.hpp>
|
||||
|
||||
#include "doctest/doctest.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class clazz {
|
||||
public:
|
||||
int v1{1};
|
||||
int v2{2};
|
||||
|
||||
clazz() = default;
|
||||
clazz(int v): v1{v}, v2{v} {}
|
||||
clazz(int v1, int v2): v1{v1}, v2{v2} {}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/ctor") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
const meta::ctor_info ctor0 = meta::ctor_<>().make_info<clazz>();
|
||||
const meta::ctor_info ctor1 = meta::ctor_<int>().make_info<clazz>();
|
||||
const meta::ctor_info ctor2 = meta::ctor_<int, int>().make_info<clazz>();
|
||||
|
||||
SUBCASE("arity") {
|
||||
CHECK(ctor0.arity() == 0u);
|
||||
CHECK(ctor1.arity() == 1u);
|
||||
CHECK(ctor2.arity() == 2u);
|
||||
}
|
||||
|
||||
SUBCASE("return_type") {
|
||||
CHECK(ctor0.return_type() == meta::get_family_id<clazz>());
|
||||
CHECK(ctor1.return_type() == meta::get_family_id<clazz>());
|
||||
CHECK(ctor2.return_type() == meta::get_family_id<clazz>());
|
||||
}
|
||||
|
||||
SUBCASE("argument_types") {
|
||||
CHECK_FALSE(ctor0.argument_type(0u));
|
||||
|
||||
CHECK(ctor1.argument_type(0u) == meta::get_family_id<int>());
|
||||
CHECK_FALSE(ctor1.argument_type(1u));
|
||||
|
||||
CHECK(ctor2.argument_type(0u) == meta::get_family_id<int>());
|
||||
CHECK(ctor2.argument_type(1u) == meta::get_family_id<int>());
|
||||
CHECK_FALSE(ctor2.argument_type(2u));
|
||||
}
|
||||
|
||||
SUBCASE("invoke0") {
|
||||
CHECK(ctor0().cast<const clazz&>().v1 == 1);
|
||||
CHECK(ctor0().cast<const clazz&>().v2 == 2);
|
||||
CHECK_THROWS_AS(ctor0(1), std::logic_error);
|
||||
|
||||
CHECK(ctor0.invoke().cast<const clazz&>().v1 == 1);
|
||||
CHECK(ctor0.invoke().cast<const clazz&>().v2 == 2);
|
||||
CHECK_THROWS_AS(ctor0.invoke(1), std::logic_error);
|
||||
|
||||
CHECK(ctor0.invoke_r<const clazz&>().v1 == 1);
|
||||
CHECK(ctor0.invoke_r<const clazz&>().v2 == 2);
|
||||
CHECK_THROWS_AS(ctor0.invoke_r<const clazz&>(1), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("invoke1") {
|
||||
CHECK(ctor1(42).cast<const clazz&>().v1 == 42);
|
||||
CHECK(ctor1(42).cast<const clazz&>().v2 == 42);
|
||||
CHECK_THROWS_AS(ctor1(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor1(1,1), std::logic_error);
|
||||
|
||||
CHECK(ctor1.invoke(42).cast<const clazz&>().v1 == 42);
|
||||
CHECK(ctor1.invoke(42).cast<const clazz&>().v2 == 42);
|
||||
CHECK_THROWS_AS(ctor1.invoke(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor1.invoke(1,1), std::logic_error);
|
||||
|
||||
CHECK(ctor1.invoke_r<const clazz&>(42).v1 == 42);
|
||||
CHECK(ctor1.invoke_r<const clazz&>(42).v2 == 42);
|
||||
CHECK_THROWS_AS(ctor1.invoke_r<const clazz&>(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor1.invoke_r<const clazz&>(1,1), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("invoke2") {
|
||||
CHECK(ctor2(21,42).cast<const clazz&>().v1 == 21);
|
||||
CHECK(ctor2(21,42).cast<const clazz&>().v2 == 42);
|
||||
CHECK_THROWS_AS(ctor2(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2(1), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2(1,1,1), std::logic_error);
|
||||
|
||||
CHECK(ctor2.invoke(21,42).cast<const clazz&>().v1 == 21);
|
||||
CHECK(ctor2.invoke(21,42).cast<const clazz&>().v2 == 42);
|
||||
CHECK_THROWS_AS(ctor2.invoke(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2.invoke(1), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2.invoke(1,1,1), std::logic_error);
|
||||
|
||||
CHECK(ctor2.invoke_r<const clazz&>(21,42).v1 == 21);
|
||||
CHECK(ctor2.invoke_r<const clazz&>(21,42).v2 == 42);
|
||||
CHECK_THROWS_AS(ctor2.invoke_r<const clazz&>(), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2.invoke_r<const clazz&>(1), std::logic_error);
|
||||
CHECK_THROWS_AS(ctor2.invoke_r<const clazz&>(1,1,1), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("is_invocable") {
|
||||
CHECK(ctor0.is_invocable<>());
|
||||
CHECK_FALSE(ctor0.is_invocable<int>());
|
||||
|
||||
CHECK(ctor1.is_invocable<int>());
|
||||
CHECK_FALSE(ctor1.is_invocable<float>());
|
||||
CHECK_FALSE(ctor1.is_invocable<>());
|
||||
CHECK_FALSE(ctor1.is_invocable<int, int>());
|
||||
|
||||
CHECK(ctor2.is_invocable<int, int>());
|
||||
CHECK_FALSE(ctor2.is_invocable<int, float>());
|
||||
CHECK_FALSE(ctor2.is_invocable<>());
|
||||
CHECK_FALSE(ctor2.is_invocable<int>());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/ctor/class") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
const meta::class_info clazz_info = meta::class_<clazz>("clazz")(
|
||||
meta::ctor_<>(),
|
||||
meta::ctor_<int>(),
|
||||
meta::ctor_<int, int>()
|
||||
).make_info();
|
||||
|
||||
CHECK(clazz_info.get_ctor<>());
|
||||
CHECK(clazz_info.get_ctor<int>());
|
||||
CHECK(clazz_info.get_ctor<int, int>());
|
||||
|
||||
CHECK_FALSE(clazz_info.get_ctor<float>());
|
||||
CHECK_FALSE(clazz_info.get_ctor<int, float>());
|
||||
CHECK_FALSE(clazz_info.get_ctor<int, int, int>());
|
||||
}
|
||||
@@ -37,14 +37,24 @@ TEST_CASE("meta/field") {
|
||||
clazz instance;
|
||||
|
||||
CHECK(instance.field == 1);
|
||||
CHECK(field_info.get_r<int>(instance) == 1);
|
||||
CHECK(field_info(instance).cast<int>() == 1);
|
||||
CHECK(field_info.get(instance).cast<int>() == 1);
|
||||
CHECK(field_info.get_r<int>(std::as_const(instance)) == 1);
|
||||
CHECK(field_info(std::as_const(instance)).cast<int>() == 1);
|
||||
CHECK(field_info.get(std::as_const(instance)).cast<int>() == 1);
|
||||
|
||||
CHECK_NOTHROW(field_info(instance, 3));
|
||||
CHECK_NOTHROW(field_info.set(instance, 3));
|
||||
CHECK_THROWS_AS(field_info(instance, 4.f), std::logic_error);
|
||||
CHECK_THROWS_AS(field_info.set(instance, 4.f), std::logic_error);
|
||||
|
||||
CHECK(instance.field == 3);
|
||||
CHECK(field_info.get_r<int>(instance) == 3);
|
||||
CHECK(field_info(instance).cast<int>() == 3);
|
||||
CHECK(field_info.get(instance).cast<int>() == 3);
|
||||
CHECK(field_info.get_r<int>(std::as_const(instance)) == 3);
|
||||
CHECK(field_info(std::as_const(instance)).cast<int>() == 3);
|
||||
CHECK(field_info.get(std::as_const(instance)).cast<int>() == 3);
|
||||
}
|
||||
|
||||
@@ -52,13 +62,22 @@ TEST_CASE("meta/field") {
|
||||
clazz instance;
|
||||
|
||||
CHECK(instance.cfield == 2);
|
||||
CHECK(cfield_info.get_r<int>(instance) == 2);
|
||||
CHECK(cfield_info(instance).cast<int>() == 2);
|
||||
CHECK(cfield_info.get(instance).cast<int>() == 2);
|
||||
CHECK(cfield_info.get_r<int>(std::as_const(instance)) == 2);
|
||||
CHECK(cfield_info(std::as_const(instance)).cast<int>() == 2);
|
||||
CHECK(cfield_info.get(std::as_const(instance)).cast<int>() == 2);
|
||||
|
||||
CHECK_THROWS_AS(cfield_info(instance, 4), std::logic_error);
|
||||
CHECK_THROWS_AS(cfield_info.set(instance, 4), std::logic_error);
|
||||
|
||||
CHECK(instance.cfield == 2);
|
||||
CHECK(cfield_info.get_r<int>(instance) == 2);
|
||||
CHECK(cfield_info(instance).cast<int>() == 2);
|
||||
CHECK(cfield_info.get(instance).cast<int>() == 2);
|
||||
CHECK(cfield_info.get_r<int>(std::as_const(instance)) == 2);
|
||||
CHECK(cfield_info(std::as_const(instance)).cast<int>() == 2);
|
||||
CHECK(cfield_info.get(std::as_const(instance)).cast<int>() == 2);
|
||||
}
|
||||
|
||||
@@ -66,7 +85,11 @@ TEST_CASE("meta/field") {
|
||||
clazz instance;
|
||||
|
||||
instance.field = 5;
|
||||
CHECK(field_info.get_r<int>(instance) == 5);
|
||||
CHECK(field_info(instance).cast<int>() == 5);
|
||||
CHECK(field_info.get(instance).cast<int>() == 5);
|
||||
CHECK(field_info.get_r<int>(std::as_const(instance)) == 5);
|
||||
CHECK(field_info(std::as_const(instance)).cast<int>() == 5);
|
||||
CHECK(field_info.get(std::as_const(instance)).cast<int>() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,33 +64,52 @@ TEST_CASE("meta/function") {
|
||||
}
|
||||
|
||||
SUBCASE("void_return") {
|
||||
CHECK_NOTHROW(void_f_void_info.invoke());
|
||||
CHECK_FALSE(void_f_void_info());
|
||||
CHECK_FALSE(void_f_void_info.invoke());
|
||||
CHECK_FALSE(void_f_void_info.invoke_r<int>());
|
||||
CHECK_THROWS_AS(void_f_void_info(1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int_info(), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int_info.invoke(1));
|
||||
CHECK_FALSE(void_f_int_info(1));
|
||||
CHECK_FALSE(void_f_int_info.invoke(1));
|
||||
CHECK_FALSE(void_f_int_info.invoke_r<int>(1));
|
||||
CHECK_THROWS_AS(void_f_int_info(1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info(1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int2_info(), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info(1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(1), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int2_info.invoke(1, 2));
|
||||
CHECK_FALSE(void_f_int2_info(1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke(1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke_r<int>(1, 2));
|
||||
CHECK_THROWS_AS(void_f_int2_info(1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info(1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info(1, 2, 3), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(1, 2, 3), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("int_return") {
|
||||
CHECK(int_f_void_info.invoke_r<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke()->cast<int>() == 1);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke(1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke_r<int>(1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(), std::logic_error);
|
||||
CHECK(int_f_int_info.invoke_r<int>(1) == 1);
|
||||
CHECK(int_f_int_info.invoke(1)->cast<int>() == 1);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(1), std::logic_error);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(1, 2) == 3);
|
||||
CHECK(int_f_int2_info.invoke(1, 2)->cast<int>() == 3);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(1, 2.f), std::logic_error);
|
||||
|
||||
@@ -83,64 +83,106 @@ TEST_CASE("meta/non_const_method") {
|
||||
|
||||
SUBCASE("another_instance") {
|
||||
clazz2 instance;
|
||||
CHECK_THROWS_AS(void_f_void_info(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke_r<int>(instance), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int_info(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke_r<int>(instance, 1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int2_info(instance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke_r<int>(instance, 1, 2), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("void_return") {
|
||||
clazz instance;
|
||||
|
||||
CHECK_NOTHROW(void_f_void_info.invoke(instance));
|
||||
CHECK_FALSE(void_f_void_info(instance));
|
||||
CHECK_FALSE(void_f_void_info.invoke(instance));
|
||||
CHECK_FALSE(void_f_void_info.invoke_r<int>(instance));
|
||||
CHECK_THROWS_AS(void_f_void_info(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke_r<int>(instance, 1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int_info.invoke(instance, 1));
|
||||
CHECK_FALSE(void_f_int_info(instance, 1));
|
||||
CHECK_FALSE(void_f_int_info.invoke(instance, 1));
|
||||
CHECK_FALSE(void_f_int_info.invoke_r<int>(instance, 1));
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int2_info.invoke(instance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info(instance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke(instance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke_r<int>(instance, 1, 2));
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error);
|
||||
|
||||
const clazz& cinstance = instance;
|
||||
CHECK_THROWS_AS(void_f_void_info(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke_r<int>(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke_r<int>(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info(cinstance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(cinstance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke_r<int>(cinstance, 1, 2), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("int_return") {
|
||||
clazz instance;
|
||||
|
||||
CHECK(int_f_void_info(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke_r<int>(instance) == 1);
|
||||
CHECK_THROWS_AS(int_f_void_info(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke_r<int>(instance, 1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance), std::logic_error);
|
||||
CHECK(int_f_int_info(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke_r<int>(instance, 1) == 1);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK(int_f_int2_info(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(instance, 1, 2) == 3);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error);
|
||||
|
||||
const clazz& cinstance = instance;
|
||||
CHECK_THROWS_AS(int_f_void_info(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke_r<int>(cinstance), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke_r<int>(cinstance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info(cinstance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(cinstance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke_r<int>(cinstance, 1, 2), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("int_return_by_value") {
|
||||
meta::value instance{clazz{}};
|
||||
CHECK(int_f_void_info(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke_r<int>(instance) == 1);
|
||||
CHECK(int_f_int_info(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke_r<int>(instance, 1) == 1);
|
||||
CHECK(int_f_int2_info(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(instance, 1, 2) == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,63 +228,90 @@ TEST_CASE("meta/const_method") {
|
||||
|
||||
SUBCASE("another_instance") {
|
||||
const clazz2 instance;
|
||||
CHECK_THROWS_AS(void_f_void_info(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info(instance, 1, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2), std::logic_error);
|
||||
}
|
||||
|
||||
SUBCASE("void_return") {
|
||||
clazz instance;
|
||||
|
||||
CHECK_NOTHROW(void_f_void_info.invoke(instance));
|
||||
CHECK_FALSE(void_f_void_info(instance));
|
||||
CHECK_FALSE(void_f_void_info.invoke(instance));
|
||||
CHECK_THROWS_AS(void_f_void_info.invoke(instance, 1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int_info.invoke(instance, 1));
|
||||
CHECK_FALSE(void_f_int_info(instance, 1));
|
||||
CHECK_FALSE(void_f_int_info.invoke(instance, 1));
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK_NOTHROW(void_f_int2_info.invoke(instance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info(instance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke(instance, 1, 2));
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error);
|
||||
|
||||
const clazz& cinstance = instance;
|
||||
CHECK_NOTHROW(void_f_void_info.invoke(cinstance));
|
||||
CHECK_NOTHROW(void_f_int_info.invoke(cinstance, 1));
|
||||
CHECK_NOTHROW(void_f_int2_info.invoke(cinstance, 1, 2));
|
||||
CHECK_FALSE(void_f_void_info(cinstance));
|
||||
CHECK_FALSE(void_f_void_info.invoke(cinstance));
|
||||
CHECK_FALSE(void_f_int_info(cinstance, 1));
|
||||
CHECK_FALSE(void_f_int_info.invoke(cinstance, 1));
|
||||
CHECK_FALSE(void_f_int2_info(cinstance, 1, 2));
|
||||
CHECK_FALSE(void_f_int2_info.invoke(cinstance, 1, 2));
|
||||
}
|
||||
|
||||
SUBCASE("int_return") {
|
||||
clazz instance;
|
||||
|
||||
CHECK(int_f_void_info(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke_r<int>(instance) == 1);
|
||||
CHECK_THROWS_AS(int_f_void_info.invoke(instance, 1), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance), std::logic_error);
|
||||
CHECK(int_f_int_info(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke_r<int>(instance, 1) == 1);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1.f), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1, 2), std::logic_error);
|
||||
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1), std::logic_error);
|
||||
CHECK(int_f_int2_info(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(instance, 1, 2) == 3);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1.f, 2), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2.f), std::logic_error);
|
||||
CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error);
|
||||
|
||||
const clazz& cinstance = instance;
|
||||
CHECK(int_f_void_info(cinstance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke(cinstance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke_r<int>(cinstance) == 1);
|
||||
CHECK(int_f_int_info(cinstance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke(cinstance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke_r<int>(cinstance, 1) == 1);
|
||||
CHECK(int_f_int2_info(cinstance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke(cinstance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(cinstance, 1, 2) == 3);
|
||||
}
|
||||
|
||||
SUBCASE("int_return_by_value") {
|
||||
meta::value instance{clazz{}};
|
||||
CHECK(int_f_void_info(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke(instance)->cast<int>() == 1);
|
||||
CHECK(int_f_void_info.invoke_r<int>(instance) == 1);
|
||||
CHECK(int_f_int_info(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke(instance, 1)->cast<int>() == 1);
|
||||
CHECK(int_f_int_info.invoke_r<int>(instance, 1) == 1);
|
||||
CHECK(int_f_int2_info(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast<int>() == 3);
|
||||
CHECK(int_f_int2_info.invoke_r<int>(instance, 1, 2) == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +69,25 @@ TEST_CASE("meta/value") {
|
||||
CHECK(meta::value{std::in_place_type<std::uint64_t>, std::uint64_t{1}}.is_uint64());
|
||||
CHECK(meta::value{std::in_place_type<std::size_t>, std::size_t{1}}.is_size_t());
|
||||
CHECK(meta::value{std::in_place_type<std::uintptr_t>, std::uintptr_t{1}}.is_uintptr_t());
|
||||
|
||||
SUBCASE("in_place") {
|
||||
CHECK(meta::value{std::in_place_type<std::uint8_t>, std::uint8_t{1}}.is_uint8());
|
||||
CHECK(meta::value{std::in_place_type<std::uint8_t&>, std::uint8_t{1}}.is_uint8());
|
||||
CHECK(meta::value{std::in_place_type<const std::uint8_t>, std::uint8_t{1}}.is_uint8());
|
||||
CHECK(meta::value{std::in_place_type<const std::uint8_t&>, std::uint8_t{1}}.is_uint8());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/value/fid") {
|
||||
namespace meta = meta_hpp;
|
||||
using namespace std::string_literals;
|
||||
|
||||
CHECK(meta::value{clazz{}}.has_type<clazz>());
|
||||
CHECK(meta::value{clazz{}}.fid() == meta::get_family_id<clazz>());
|
||||
|
||||
CHECK(meta::value{clazz2{}}.has_type<clazz2>());
|
||||
CHECK(meta::value{clazz2{}}.fid() == meta::get_family_id<clazz2>());
|
||||
|
||||
CHECK(meta::value{clazz{}}.fid() != meta::value{clazz2{}}.fid());
|
||||
|
||||
{
|
||||
|
||||
@@ -39,28 +39,41 @@ TEST_CASE("meta/variable") {
|
||||
|
||||
{
|
||||
CHECK(variable == 1);
|
||||
CHECK(variable_info().cast<int>() == 1);
|
||||
CHECK(variable_info.get().cast<int>() == 1);
|
||||
CHECK(variable_info.get_r<int>() == 1);
|
||||
|
||||
CHECK_NOTHROW(variable_info(3));
|
||||
CHECK_NOTHROW(variable_info.set(3));
|
||||
CHECK_THROWS_AS(variable_info(4.f), std::logic_error);
|
||||
CHECK_THROWS_AS(variable_info.set(4.f), std::logic_error);
|
||||
|
||||
CHECK(variable == 3);
|
||||
CHECK(variable_info().cast<int>() == 3);
|
||||
CHECK(variable_info.get().cast<int>() == 3);
|
||||
CHECK(variable_info.get_r<int>() == 3);
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(cvariable == 2);
|
||||
CHECK(cvariable_info().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get_r<int>() == 2);
|
||||
|
||||
CHECK_THROWS_AS(cvariable_info(4), std::logic_error);
|
||||
CHECK_THROWS_AS(cvariable_info.set(4), std::logic_error);
|
||||
|
||||
CHECK(cvariable == 2);
|
||||
CHECK(cvariable_info().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get_r<int>() == 2);
|
||||
}
|
||||
|
||||
{
|
||||
variable = 5;
|
||||
CHECK(variable_info().cast<int>() == 5);
|
||||
CHECK(variable_info.get().cast<int>() == 5);
|
||||
CHECK(variable_info.get_r<int>() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,27 +91,39 @@ TEST_CASE("meta/variable") {
|
||||
|
||||
{
|
||||
CHECK(clazz::variable == 1);
|
||||
CHECK(variable_info().cast<int>() == 1);
|
||||
CHECK(variable_info.get().cast<int>() == 1);
|
||||
CHECK(variable_info.get_r<int>() == 1);
|
||||
|
||||
CHECK_NOTHROW(variable_info(3));
|
||||
CHECK_NOTHROW(variable_info.set(3));
|
||||
|
||||
CHECK(clazz::variable == 3);
|
||||
CHECK(variable_info().cast<int>() == 3);
|
||||
CHECK(variable_info.get().cast<int>() == 3);
|
||||
CHECK(variable_info.get_r<int>() == 3);
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(clazz::cvariable == 2);
|
||||
CHECK(cvariable_info().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get_r<int>() == 2);
|
||||
|
||||
CHECK_THROWS_AS(cvariable_info(4), std::logic_error);
|
||||
CHECK_THROWS_AS(cvariable_info.set(4), std::logic_error);
|
||||
|
||||
CHECK(clazz::cvariable == 2);
|
||||
CHECK(cvariable_info().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get().cast<int>() == 2);
|
||||
CHECK(cvariable_info.get_r<int>() == 2);
|
||||
}
|
||||
|
||||
{
|
||||
clazz::variable = 5;
|
||||
CHECK(variable_info().cast<int>() == 5);
|
||||
CHECK(variable_info.get().cast<int>() == 5);
|
||||
CHECK(variable_info.get_r<int>() == 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user