add value return policy

This commit is contained in:
BlackMATov
2022-01-21 22:01:57 +07:00
parent 79b26bef09
commit b414e71d8f
19 changed files with 601 additions and 240 deletions

View File

@@ -31,6 +31,7 @@ target_compile_options(${PROJECT_NAME}
-Wno-exit-time-destructors
-Wno-extra-semi-stmt
-Wno-float-equal
-Wno-global-constructors
-Wno-padded
-Wno-reserved-identifier
-Wno-shadow-field

View File

@@ -1,7 +1,6 @@
# meta.hpp
- add array value access
- add return value policy
- add dtors
- add meta exception class;
- void value?
- all string to hash?

View File

@@ -9,68 +9,63 @@
#include "meta_base.hpp"
#include "meta_states.hpp"
namespace meta_hpp::detail
{
template < typename Class, typename... Args >
concept class_bind_ctor_kind =
class_kind<Class> &&
requires(Args&&... args) { { Class{std::forward<Args>(args)...} }; };
template < typename Class, typename Base >
concept class_bind_base_kind =
class_kind<Class> && class_kind<Base> &&
stdex::derived_from<Class, Base>;
template < typename Class, typename Function >
concept class_bind_function_kind =
class_kind<Class> && function_kind<Function>;
template < typename Class, typename Member >
concept class_bind_member_kind =
class_kind<Class> && member_kind<Member> &&
stdex::same_as<Class, typename member_traits<Member>::class_type>;
template < typename Class, typename Method >
concept class_bind_method_kind =
class_kind<Class> && method_kind<Method> &&
stdex::same_as<Class, typename method_traits<Method>::class_type>;
template < typename Class, typename Pointer >
concept class_bind_variable_kind =
class_kind<Class> && pointer_kind<Pointer>;
}
namespace meta_hpp
{
namespace detail
{
template < typename Class, typename... Args >
concept class_bind_ctor_kind =
class_kind<Class> &&
requires(Args&&... args) { { Class{std::forward<Args>(args)...} }; };
template < typename Class, typename Base >
concept class_bind_base_kind =
class_kind<Class> && class_kind<Base> &&
stdex::derived_from<Class, Base>;
template < typename Class, typename Member >
concept class_bind_member_kind =
class_kind<Class> && member_kind<Member> &&
stdex::same_as<Class, typename member_traits<Member>::class_type>;
template < typename Class, typename Method >
concept class_bind_method_kind =
class_kind<Class> && method_kind<Method> &&
stdex::same_as<Class, typename method_traits<Method>::class_type>;
}
template < detail::class_kind Class >
class class_bind final {
public:
explicit class_bind();
operator class_type() const noexcept;
template < typename... Args >
requires detail::class_bind_ctor_kind<Class, Args...>
class_bind& ctor_();
template < typename... Args
, ctor_policy_kind Policy = ctor_policy::as_object >
class_bind& ctor_(Policy = Policy{})
requires detail::class_bind_ctor_kind<Class, Args...>;
template < detail::class_kind Base >
requires detail::class_bind_base_kind<Class, Base>
class_bind& base_();
class_bind& base_()
requires detail::class_bind_base_kind<Class, Base>;
template < detail::function_kind Function >
requires detail::class_bind_function_kind<Class, Function>
class_bind& function_(std::string name, Function function);
template < detail::function_kind Function
, function_policy_kind Policy = function_policy::as_copy >
class_bind& function_(std::string name, Function function, Policy = Policy{});
template < detail::member_kind Member >
requires detail::class_bind_member_kind<Class, Member>
class_bind& member_(std::string name, Member member);
template < detail::member_kind Member
, member_policy_kind Policy = member_policy::as_copy >
class_bind& member_(std::string name, Member member, Policy = Policy{})
requires detail::class_bind_member_kind<Class, Member>;
template < detail::method_kind Method >
requires detail::class_bind_method_kind<Class, Method>
class_bind& method_(std::string name, Method method);
template < detail::method_kind Method
, method_policy_kind Policy = method_policy::as_copy >
class_bind& method_(std::string name, Method method, Policy = Policy{})
requires detail::class_bind_method_kind<Class, Method>;
template < detail::pointer_kind Pointer >
requires detail::class_bind_variable_kind<Class, Pointer>
class_bind& variable_(std::string name, Pointer pointer);
template < detail::pointer_kind Pointer
, variable_policy_kind Policy = variable_policy::as_copy >
class_bind& variable_(std::string name, Pointer pointer, Policy = Policy{});
private:
detail::class_type_data_ptr data_;
};
@@ -107,11 +102,13 @@ namespace meta_hpp
template < detail::enum_kind Enum >
scope_bind& enum_(std::string name);
template < detail::function_kind Function >
scope_bind& function_(std::string name, Function function);
template < detail::function_kind Function
, function_policy_kind Policy = function_policy::as_copy >
scope_bind& function_(std::string name, Function function, Policy = Policy{});
template < detail::pointer_kind Pointer >
scope_bind& variable_(std::string name, Pointer pointer);
template < detail::pointer_kind Pointer
, variable_policy_kind Policy = variable_policy::as_copy >
scope_bind& variable_(std::string name, Pointer pointer, Policy = Policy{});
private:
detail::scope_state_ptr state_;
};

View File

@@ -21,18 +21,21 @@ namespace meta_hpp
}
template < detail::class_kind Class >
template < typename... Args >
template < typename... Args, ctor_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
class_bind<Class>& class_bind<Class>::ctor_(Policy)
requires detail::class_bind_ctor_kind<Class, Args...>
class_bind<Class>& class_bind<Class>::ctor_() {
auto ctor_state = detail::ctor_state::make<Class, Args...>();
{
auto ctor_state = detail::ctor_state::make<Policy, Class, Args...>();
data_->ctors.emplace(ctor_state->index, std::move(ctor_state));
return *this;
}
template < detail::class_kind Class >
template < detail::class_kind Base >
class_bind<Class>& class_bind<Class>::base_()
requires detail::class_bind_base_kind<Class, Base>
class_bind<Class>& class_bind<Class>::base_() {
{
data_->bases.emplace(resolve_type<Base>());
data_->bases_info.emplace(resolve_type<Base>(), detail::class_type_data::base_info{
.upcast = +[](void* derived) -> void* {
@@ -43,37 +46,41 @@ namespace meta_hpp
}
template < detail::class_kind Class >
template < detail::function_kind Function >
requires detail::class_bind_function_kind<Class, 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));
template < detail::function_kind Function, function_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
class_bind<Class>& class_bind<Class>::function_(std::string name, Function function, Policy) {
auto function_state = detail::function_state::make<Policy>(std::move(name), std::move(function));
data_->functions.emplace(function_state->index, std::move(function_state));
return *this;
}
template < detail::class_kind Class >
template < detail::member_kind Member >
template < detail::member_kind Member, member_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
class_bind<Class>& class_bind<Class>::member_(std::string name, Member member, Policy)
requires detail::class_bind_member_kind<Class, 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));
{
auto member_state = detail::member_state::make<Policy>(std::move(name), std::move(member));
data_->members.emplace(member_state->index, std::move(member_state));
return *this;
}
template < detail::class_kind Class >
template < detail::method_kind Method >
template < detail::method_kind Method, method_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
class_bind<Class>& class_bind<Class>::method_(std::string name, Method method, Policy)
requires detail::class_bind_method_kind<Class, 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));
{
auto method_state = detail::method_state::make<Policy>(std::move(name), std::move(method));
data_->methods.emplace(method_state->index, std::move(method_state));
return *this;
}
template < detail::class_kind Class >
template < detail::pointer_kind Pointer >
requires detail::class_bind_variable_kind<Class, 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));
template < detail::pointer_kind Pointer, variable_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
class_bind<Class>& class_bind<Class>::variable_(std::string name, Pointer pointer, Policy) {
auto variable_state = detail::variable_state::make<Policy>(std::move(name), std::move(pointer));
data_->variables.emplace(variable_state->index, std::move(variable_state));
return *this;
}

View File

@@ -35,16 +35,18 @@ namespace meta_hpp
return *this;
}
template < detail::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));
template < detail::function_kind Function, function_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
scope_bind& scope_bind::function_(std::string name, Function function, Policy) {
auto function_state = detail::function_state::make<Policy>(std::move(name), std::move(function));
state_->functions.emplace(function_state->index, std::move(function_state));
return *this;
}
template < detail::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));
template < detail::pointer_kind Pointer, variable_policy_kind Policy >
// NOLINTNEXTLINE(readability-named-parameter)
scope_bind& scope_bind::variable_(std::string name, Pointer pointer, Policy) {
auto variable_state = detail::variable_state::make<Policy>(std::move(name), std::move(pointer));
state_->variables.emplace(variable_state->index, std::move(variable_state));
return *this;
}

View File

@@ -57,6 +57,74 @@ namespace meta_hpp
}
}
namespace meta_hpp
{
namespace ctor_policy
{
struct as_object final {};
struct as_raw_pointer final {};
struct as_shared_pointer final {};
}
namespace function_policy
{
struct as_copy final {};
struct discard_return final {};
struct return_reference_as_pointer final {};
}
namespace member_policy
{
struct as_copy final {};
struct as_pointer final {};
struct as_reference_wrapper final {};
};
namespace method_policy
{
struct as_copy final {};
struct discard_return final {};
struct return_reference_as_pointer final {};
};
namespace variable_policy
{
struct as_copy final {};
struct as_pointer final {};
struct as_reference_wrapper final {};
};
template < typename Policy >
concept ctor_policy_kind =
detail::stdex::same_as<Policy, ctor_policy::as_object> ||
detail::stdex::same_as<Policy, ctor_policy::as_raw_pointer> ||
detail::stdex::same_as<Policy, ctor_policy::as_shared_pointer>;
template < typename Policy >
concept function_policy_kind =
detail::stdex::same_as<Policy, function_policy::as_copy> ||
detail::stdex::same_as<Policy, function_policy::discard_return> ||
detail::stdex::same_as<Policy, function_policy::return_reference_as_pointer>;
template < typename Policy >
concept member_policy_kind =
detail::stdex::same_as<Policy, member_policy::as_copy> ||
detail::stdex::same_as<Policy, member_policy::as_pointer> ||
detail::stdex::same_as<Policy, member_policy::as_reference_wrapper>;
template < typename Policy >
concept method_policy_kind =
detail::stdex::same_as<Policy, method_policy::as_copy> ||
detail::stdex::same_as<Policy, method_policy::discard_return> ||
detail::stdex::same_as<Policy, method_policy::return_reference_as_pointer>;
template < typename Policy >
concept variable_policy_kind =
detail::stdex::same_as<Policy, variable_policy::as_copy> ||
detail::stdex::same_as<Policy, variable_policy::as_pointer> ||
detail::stdex::same_as<Policy, variable_policy::as_reference_wrapper>;
}
namespace meta_hpp
{
class ctor final {
@@ -267,10 +335,7 @@ namespace meta_hpp::detail
const invoke_impl invoke;
const is_invocable_with_impl is_invocable_with;
template < class_kind Class, typename... Args >
explicit ctor_state(ctor_index index, type_list<Class>, type_list<Args...>);
template < class_kind Class, typename... Args >
template < ctor_policy_kind Policy, class_kind Class, typename... Args >
[[nodiscard]] static ctor_state_ptr make();
};
@@ -279,9 +344,6 @@ namespace meta_hpp::detail
const value enum_value;
const value underlying_value;
template < enum_kind Enum >
explicit evalue_state(evalue_index index, Enum value);
template < enum_kind Enum >
[[nodiscard]] static evalue_state_ptr make(std::string name, Enum value);
};
@@ -294,10 +356,7 @@ namespace meta_hpp::detail
const invoke_impl invoke;
const is_invocable_with_impl is_invocable_with;
template < function_kind Function >
explicit function_state(function_index index, Function function);
template < function_kind Function >
template < function_policy_kind Policy, function_kind Function >
[[nodiscard]] static function_state_ptr make(std::string name, Function function);
};
@@ -314,10 +373,7 @@ namespace meta_hpp::detail
const is_gettable_with_impl is_gettable_with;
const is_settable_with_impl is_settable_with;
template < member_kind Member >
explicit member_state(member_index index, Member member);
template < member_kind Member >
template < member_policy_kind Policy, member_kind Member >
[[nodiscard]] static member_state_ptr make(std::string name, Member member);
};
@@ -329,10 +385,7 @@ namespace meta_hpp::detail
const invoke_impl invoke;
const is_invocable_with_impl is_invocable_with;
template < method_kind Method >
explicit method_state(method_index index, Method method);
template < method_kind Method >
template < method_policy_kind Policy, method_kind Method >
[[nodiscard]] static method_state_ptr make(std::string name, Method method);
};
@@ -344,8 +397,6 @@ namespace meta_hpp::detail
function_map functions;
variable_map variables;
explicit scope_state(scope_index index);
[[nodiscard]] static scope_state_ptr make(std::string name);
[[nodiscard]] static scope_state_ptr get_static(std::string_view name);
};
@@ -360,10 +411,7 @@ namespace meta_hpp::detail
const setter_impl setter;
const is_settable_with_impl is_settable_with;
template < pointer_kind Pointer >
explicit variable_state(variable_index index, Pointer pointer);
template < pointer_kind Pointer >
template < variable_policy_kind Policy, pointer_kind Pointer >
[[nodiscard]] static variable_state_ptr make(std::string name, Pointer pointer);
};
}

View File

@@ -13,29 +13,55 @@
namespace meta_hpp::detail
{
template < class_kind Class, typename... Args >
value vargs_invoke(std::span<const arg> args) {
template < ctor_policy_kind Policy, class_kind Class, typename... Args >
value raw_ctor_invoke(std::span<const arg> args) {
using ct = ctor_traits<Class, Args...>;
using class_type = typename ct::class_type;
using argument_types = typename ct::argument_types;
constexpr bool as_object =
stdex::copy_constructible<class_type> &&
stdex::same_as<Policy, ctor_policy::as_object>;
constexpr bool as_raw_ptr =
stdex::same_as<Policy, ctor_policy::as_raw_pointer>;
constexpr bool as_shared_ptr =
stdex::same_as<Policy, ctor_policy::as_shared_pointer>;
static_assert(as_object || as_raw_ptr || as_shared_ptr);
if ( args.size() != ct::arity ) {
throw std::logic_error("an attempt to call a constructor with an incorrect arity");
}
return std::invoke([
args
// NOLINTNEXTLINE(readability-named-parameter)
return std::invoke([&args]<std::size_t... Is>(std::index_sequence<Is...>){
]<std::size_t... Is>(std::index_sequence<Is...>) -> value {
if ( !(... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a constructor with incorrect argument types");
}
class_type return_value{(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...};
return value{std::forward<class_type>(return_value)};
if constexpr ( as_object ) {
class_type return_value{(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...};
return value{std::move(return_value)};
}
if constexpr ( as_raw_ptr ) {
auto return_value{std::make_unique<class_type>((args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
return value{return_value.release()};
}
if constexpr ( as_shared_ptr ) {
auto return_value{std::make_shared<class_type>((args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
return value{std::move(return_value)};
}
}, std::make_index_sequence<ct::arity>());
}
template < class_kind Class, typename... Args >
bool vargs_is_invocable_with(std::span<const arg_base> args) {
bool raw_ctor_is_invocable_with(std::span<const arg_base> args) {
using ct = ctor_traits<Class, Args...>;
using argument_types = typename ct::argument_types;
@@ -44,7 +70,7 @@ namespace meta_hpp::detail
}
// NOLINTNEXTLINE(readability-named-parameter)
return std::invoke([&args]<std::size_t... Is>(std::index_sequence<Is...>){
return std::invoke([args]<std::size_t... Is>(std::index_sequence<Is...>){
return (... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>());
}, std::make_index_sequence<ct::arity>());
}
@@ -52,32 +78,29 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
template < class_kind Class, typename... Args >
template < ctor_policy_kind Policy, class_kind Class, typename... Args >
ctor_state::invoke_impl make_ctor_invoke() {
using namespace std::placeholders;
return std::bind(&vargs_invoke<Class, Args...>, _1);
return std::bind(&raw_ctor_invoke<Policy, Class, Args...>, _1);
}
template < class_kind Class, typename... Args >
ctor_state::is_invocable_with_impl make_ctor_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&vargs_is_invocable_with<Class, Args...>, _1);
return std::bind(&raw_ctor_is_invocable_with<Class, Args...>, _1);
}
}
namespace meta_hpp::detail
{
template < class_kind Class, typename... Args >
// NOLINTNEXTLINE(readability-named-parameter)
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...>()} {}
template < class_kind Class, typename... Args >
template < ctor_policy_kind Policy, class_kind Class, typename... Args >
ctor_state_ptr ctor_state::make() {
ctor_index index{ctor_type_data::get_static<Class, Args...>()};
return std::make_shared<ctor_state>(std::move(index), type_list<Class>{}, type_list<Args...>{});
return std::make_shared<ctor_state>(ctor_state{
.index{std::move(index)},
.invoke{make_ctor_invoke<Policy, Class, Args...>()},
.is_invocable_with{make_ctor_is_invocable_with<Class, Args...>()},
});
}
}

View File

@@ -13,16 +13,14 @@
namespace meta_hpp::detail
{
template < enum_kind Enum >
evalue_state::evalue_state(evalue_index index, Enum value)
: index{std::move(index)}
, enum_value{value}
, underlying_value{stdex::to_underlying(value)} {}
template < enum_kind Enum >
evalue_state_ptr evalue_state::make(std::string name, Enum value) {
evalue_index index{enum_type_data::get_static<Enum>(), std::move(name)};
return std::make_shared<evalue_state>(std::move(index), std::move(value));
return std::make_shared<evalue_state>(evalue_state{
.index{std::move(index)},
.enum_value{value},
.underlying_value{stdex::to_underlying(value)},
});
}
}

View File

@@ -13,38 +13,59 @@
namespace meta_hpp::detail
{
template < function_kind Function >
std::optional<value> vargs_invoke(Function function, std::span<const arg> args) {
template < function_policy_kind Policy, function_kind Function >
std::optional<value> raw_function_invoke(Function function, std::span<const arg> args) {
using ft = function_traits<Function>;
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
constexpr bool as_copy =
stdex::copy_constructible<return_type> &&
stdex::same_as<Policy, function_policy::as_copy>;
constexpr bool as_void =
std::is_void_v<return_type> ||
stdex::same_as<Policy, function_policy::discard_return>;
constexpr bool ref_as_ptr =
std::is_reference_v<return_type> &&
stdex::same_as<Policy, function_policy::return_reference_as_pointer>;
static_assert(as_copy || as_void || ref_as_ptr);
if ( args.size() != ft::arity ) {
throw std::logic_error("an attempt to call a function with an incorrect arity");
}
return std::invoke([
args, function = std::move(function)
// NOLINTNEXTLINE(readability-named-parameter)
return std::invoke([function = std::move(function), &args]<std::size_t... Is>(std::index_sequence<Is...>){
]<std::size_t... Is>(std::index_sequence<Is...>) -> std::optional<value> {
if ( !(... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a function with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(
if constexpr ( as_void ) {
std::ignore = std::invoke(
std::move(function),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
return std::nullopt;
} else {
return_type return_value{std::invoke(
return_type&& return_value = std::invoke(
std::move(function),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
return value{std::forward<return_type>(return_value)};
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
if constexpr ( ref_as_ptr ) {
return value{std::addressof(return_value)};
} else {
return value{std::forward<decltype(return_value)>(return_value)};
}
}
}, std::make_index_sequence<ft::arity>());
}
template < function_kind Function >
bool vargs_is_invocable_with(std::span<const arg_base> args) {
bool raw_function_is_invocable_with(std::span<const arg_base> args) {
using ft = function_traits<Function>;
using argument_types = typename ft::argument_types;
@@ -53,7 +74,7 @@ namespace meta_hpp::detail
}
// NOLINTNEXTLINE(readability-named-parameter)
return std::invoke([&args]<std::size_t... Is>(std::index_sequence<Is...>){
return std::invoke([args]<std::size_t... Is>(std::index_sequence<Is...>){
return (... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>());
}, std::make_index_sequence<ft::arity>());
}
@@ -61,31 +82,29 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
template < function_kind Function >
template < function_policy_kind Policy, function_kind Function >
function_state::invoke_impl make_function_invoke(Function function) {
using namespace std::placeholders;
return std::bind(&vargs_invoke<Function>, std::move(function), _1);
return std::bind(&raw_function_invoke<Policy, Function>, std::move(function), _1);
}
template < function_kind Function >
function_state::is_invocable_with_impl make_function_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&vargs_is_invocable_with<Function>, _1);
return std::bind(&raw_function_is_invocable_with<Function>, _1);
}
}
namespace meta_hpp::detail
{
template < function_kind Function >
function_state::function_state(function_index index, Function function)
: index{std::move(index)}
, invoke{make_function_invoke(std::move(function))}
, is_invocable_with{make_function_is_invocable_with<Function>()} {}
template < function_kind Function >
template < function_policy_kind Policy, function_kind Function >
function_state_ptr function_state::make(std::string name, Function function) {
function_index index{function_type_data::get_static<Function>(), std::move(name)};
return std::make_shared<function_state>(std::move(index), std::move(function));
return std::make_shared<function_state>(function_state{
.index{std::move(index)},
.invoke{make_function_invoke<Policy>(std::move(function))},
.is_invocable_with{make_function_is_invocable_with<Function>()},
});
}
}

View File

@@ -13,30 +13,65 @@
namespace meta_hpp::detail
{
template < member_kind Member >
value vargs_invoke(Member member, const inst& inst) {
template < member_policy_kind Policy, 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;
constexpr bool as_copy =
stdex::copy_constructible<value_type> &&
stdex::same_as<Policy, member_policy::as_copy>;
if ( !inst.can_cast_to<qualified_type>() ) {
constexpr bool as_ptr =
stdex::same_as<Policy, member_policy::as_pointer>;
constexpr bool as_ref_wrap =
stdex::same_as<Policy, member_policy::as_reference_wrapper>;
static_assert(as_copy || as_ptr || as_ref_wrap);
if ( !inst.can_cast_to<const class_type>() ) {
throw std::logic_error("an attempt to get a member with an incorrect instance type");
}
value_type return_value{std::invoke(std::move(member), inst.cast<qualified_type>())};
return value{std::forward<value_type>(return_value)};
if ( inst.is_const() ) {
auto&& return_value = std::invoke(std::move(member), inst.cast<const class_type>());
if constexpr ( as_copy ) {
return value{std::forward<decltype(return_value)>(return_value)};
}
if constexpr ( as_ptr ) {
return value{std::addressof(return_value)};
}
if constexpr ( as_ref_wrap ) {
return value{std::ref(return_value)};
}
} else {
auto&& return_value = std::invoke(std::move(member), inst.cast<class_type>());
if constexpr ( as_copy ) {
return value{std::forward<decltype(return_value)>(return_value)};
}
if constexpr ( as_ptr ) {
return value{std::addressof(return_value)};
}
if constexpr ( as_ref_wrap ) {
return value{std::ref(return_value)};
}
}
}
template < member_kind Member >
bool vargs_is_invocable_with(const inst_base& inst) {
bool raw_member_is_gettable_with(const inst_base& inst) {
using mt = member_traits<Member>;
using class_type = typename mt::class_type;
using qualified_type = const class_type;
return inst.can_cast_to<qualified_type>();
return inst.can_cast_to<const class_type>();
}
}
@@ -48,8 +83,6 @@ namespace meta_hpp::detail
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> ) {
throw std::logic_error("an attempt to set a constant member");
} else {
@@ -57,7 +90,7 @@ namespace meta_hpp::detail
throw std::logic_error("an attempt to set a member with an const instance type");
}
if ( !inst.can_cast_to<qualified_type>() ) {
if ( !inst.can_cast_to<class_type>() ) {
throw std::logic_error("an attempt to set a member with an incorrect instance type");
}
@@ -65,7 +98,7 @@ namespace meta_hpp::detail
throw std::logic_error("an attempt to set a member with an incorrect argument type");
}
std::invoke(std::move(member), inst.cast<qualified_type>()) = arg.cast<value_type>();
std::invoke(std::move(member), inst.cast<class_type>()) = arg.cast<value_type>();
}
}
@@ -75,27 +108,25 @@ namespace meta_hpp::detail
using class_type = typename mt::class_type;
using value_type = typename mt::value_type;
using qualified_type = class_type;
return !std::is_const_v<value_type>
&& !inst.is_const()
&& inst.can_cast_to<qualified_type>()
&& inst.can_cast_to<class_type>()
&& arg.can_cast_to<value_type>();
}
}
namespace meta_hpp::detail
{
template < member_kind Member >
template < member_policy_kind Policy, member_kind Member >
member_state::getter_impl make_member_getter(Member member) {
using namespace std::placeholders;
return std::bind(&vargs_invoke<Member>, std::move(member), _1);
return std::bind(&raw_member_getter<Policy, Member>, std::move(member), _1);
}
template < member_kind Member >
member_state::is_gettable_with_impl make_member_is_gettable_with() {
using namespace std::placeholders;
return std::bind(&vargs_is_invocable_with<Member>, _1);
return std::bind(&raw_member_is_gettable_with<Member>, _1);
}
template < member_kind Member >
@@ -113,18 +144,16 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
template < member_kind Member >
member_state::member_state(member_index index, Member member)
: index{std::move(index)}
, getter{make_member_getter(std::move(member))}
, setter{make_member_setter(std::move(member))}
, is_gettable_with{make_member_is_gettable_with<Member>()}
, is_settable_with{make_member_is_settable_with<Member>()} {}
template < member_kind Member >
template < member_policy_kind Policy, member_kind Member >
member_state_ptr member_state::make(std::string name, Member member) {
member_index index{member_type_data::get_static<Member>(), std::move(name)};
return std::make_shared<member_state>(std::move(index), std::move(member));
return std::make_shared<member_state>(member_state{
.index{std::move(index)},
.getter{make_member_getter<Policy>(std::move(member))},
.setter{make_member_setter(std::move(member))},
.is_gettable_with{make_member_is_gettable_with<Member>()},
.is_settable_with{make_member_is_settable_with<Member>()},
});
}
}

View File

@@ -13,13 +13,27 @@
namespace meta_hpp::detail
{
template < method_kind Method >
std::optional<value> vargs_invoke(Method method, const inst& inst, std::span<const arg> args) {
template < method_policy_kind Policy, method_kind Method >
std::optional<value> raw_method_invoke(Method method, const inst& inst, std::span<const arg> args) {
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;
constexpr bool as_copy =
stdex::copy_constructible<return_type> &&
stdex::same_as<Policy, method_policy::as_copy>;
constexpr bool as_void =
std::is_void_v<return_type> ||
stdex::same_as<Policy, method_policy::discard_return>;
constexpr bool ref_as_ptr =
std::is_reference_v<return_type> &&
stdex::same_as<Policy, method_policy::return_reference_as_pointer>;
static_assert(as_copy || as_void || ref_as_ptr);
if ( args.size() != mt::arity ) {
throw std::logic_error("an attempt to call a method with an incorrect arity");
}
@@ -28,30 +42,38 @@ namespace meta_hpp::detail
throw std::logic_error("an attempt to call a method with an incorrect instance type");
}
return std::invoke([
&inst, &args,
method = std::move(method)
// NOLINTNEXTLINE(readability-named-parameter)
return std::invoke([method = std::move(method), &inst, &args]<std::size_t... Is>(std::index_sequence<Is...>){
]<std::size_t... Is>(std::index_sequence<Is...>) -> std::optional<value> {
if ( !(... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(
if constexpr ( as_void ) {
std::ignore = std::invoke(
std::move(method),
inst.cast<qualified_type>(),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
return std::nullopt;
} else {
return_type return_value{std::invoke(
return_type&& return_value = std::invoke(
std::move(method),
inst.cast<qualified_type>(),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...)};
return value{std::forward<return_type>(return_value)};
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
if constexpr ( ref_as_ptr ) {
return value{std::addressof(return_value)};
} else {
return value{std::forward<decltype(return_value)>(return_value)};
}
}
}, std::make_index_sequence<mt::arity>());
}
template < method_kind Method >
bool vargs_is_invocable_with(const inst_base& inst, std::span<const arg_base> args) {
bool raw_method_is_invocable_with(const inst_base& inst, std::span<const arg_base> args) {
using mt = method_traits<Method>;
using qualified_type = typename mt::qualified_type;
using argument_types = typename mt::argument_types;
@@ -73,31 +95,29 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
template < method_kind Method >
template < method_policy_kind Policy, method_kind Method >
method_state::invoke_impl make_method_invoke(Method method) {
using namespace std::placeholders;
return std::bind(&vargs_invoke<Method>, std::move(method), _1, _2);
return std::bind(&raw_method_invoke<Policy, Method>, std::move(method), _1, _2);
}
template < method_kind Method >
method_state::is_invocable_with_impl make_method_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&vargs_is_invocable_with<Method>, _1, _2);
return std::bind(&raw_method_is_invocable_with<Method>, _1, _2);
}
}
namespace meta_hpp::detail
{
template < method_kind Method >
method_state::method_state(method_index index, Method method)
: index{std::move(index)}
, invoke{make_method_invoke(std::move(method))}
, is_invocable_with{make_method_is_invocable_with<Method>()} {}
template < method_kind Method >
template < method_policy_kind Policy, method_kind Method >
method_state_ptr method_state::make(std::string name, Method method) {
method_index index{method_type_data::get_static<Method>(), std::move(name)};
return std::make_shared<method_state>(std::move(index), std::move(method));
return std::make_shared<method_state>(method_state{
.index{std::move(index)},
.invoke{make_method_invoke<Policy>(std::move(method))},
.is_invocable_with{make_method_is_invocable_with<Method>()},
});
}
}

View File

@@ -11,12 +11,11 @@
namespace meta_hpp::detail
{
inline scope_state::scope_state(scope_index index)
: index{std::move(index)} {}
inline scope_state_ptr scope_state::make(std::string name) {
scope_index index{std::move(name)};
return std::make_shared<scope_state>(std::move(index));
return std::make_shared<scope_state>(scope_state{
.index{std::move(index)},
});
}
inline scope_state_ptr scope_state::get_static(std::string_view name) {

View File

@@ -13,13 +13,36 @@
namespace meta_hpp::detail
{
template < pointer_kind Pointer >
template < variable_policy_kind Policy, 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)};
constexpr bool as_copy =
stdex::copy_constructible<data_type> &&
stdex::same_as<Policy, variable_policy::as_copy>;
constexpr bool as_ptr =
stdex::same_as<Policy, variable_policy::as_pointer>;
constexpr bool as_ref_wrap =
stdex::same_as<Policy, variable_policy::as_reference_wrapper>;
static_assert(as_copy || as_ptr || as_ref_wrap);
auto&& return_value = *pointer;
if constexpr ( as_copy ) {
return value{std::forward<decltype(return_value)>(return_value)};
}
if constexpr ( as_ptr ) {
return value{std::addressof(return_value)};
}
if constexpr ( as_ref_wrap) {
return value{std::ref(return_value)};
}
}
template < pointer_kind Pointer >
@@ -33,7 +56,6 @@ namespace meta_hpp::detail
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>();
}
}
@@ -50,10 +72,10 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
template < pointer_kind Pointer >
template < variable_policy_kind Policy, pointer_kind Pointer >
variable_state::getter_impl make_variable_getter(Pointer pointer) {
using namespace std::placeholders;
return std::bind(&raw_variable_getter<Pointer>, pointer);
return std::bind(&raw_variable_getter<Policy, Pointer>, pointer);
}
template < pointer_kind Pointer >
@@ -71,17 +93,15 @@ namespace meta_hpp::detail
namespace meta_hpp::detail
{
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)}
, is_settable_with{make_variable_is_settable_with<Pointer>()} {}
template < pointer_kind Pointer >
template < variable_policy_kind Policy, pointer_kind Pointer >
variable_state_ptr variable_state::make(std::string name, Pointer pointer) {
variable_index index{pointer_type_data::get_static<Pointer>(), std::move(name)};
return std::make_shared<variable_state>(index, pointer);
return std::make_shared<variable_state>(variable_state{
.index{std::move(index)},
.getter{make_variable_getter<Policy>(std::move(pointer))},
.setter{make_variable_setter(std::move(pointer))},
.is_settable_with{make_variable_is_settable_with<Pointer>()},
});
}
}

View File

@@ -22,9 +22,9 @@ namespace meta_hpp
using namespace detail;
if constexpr ( sizeof...(Args) > 0 ) {
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
return vargs_invoke(std::forward<Function>(function), vargs);
return raw_function_invoke<function_policy::as_copy>(std::forward<Function>(function), vargs);
} else {
return vargs_invoke(std::forward<Function>(function), {});
return raw_function_invoke<function_policy::as_copy>(std::forward<Function>(function), {});
}
}
}
@@ -40,7 +40,7 @@ namespace meta_hpp
std::optional<value> invoke(Member&& member, Instance&& instance) {
using namespace detail;
const inst vinst{std::forward<Instance>(instance)};
return vargs_invoke(std::forward<Member>(member), vinst);
return raw_member_getter<member_policy::as_copy>(std::forward<Member>(member), vinst);
}
}
@@ -57,9 +57,9 @@ namespace meta_hpp
const inst vinst{std::forward<Instance>(instance)};
if constexpr ( sizeof...(Args) > 0 ) {
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
return vargs_invoke(std::forward<Method>(method), vinst, vargs);
return raw_method_invoke<method_policy::as_copy>(std::forward<Method>(method), vinst, vargs);
} else {
return vargs_invoke(std::forward<Method>(method), vinst, {});
return raw_method_invoke<method_policy::as_copy>(std::forward<Method>(method), vinst, {});
}
}
}
@@ -81,9 +81,9 @@ namespace meta_hpp
if constexpr ( sizeof...(Args) > 0 ) {
using namespace detail;
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
return vargs_is_invocable_with<Function>(vargs);
return raw_function_is_invocable_with<Function>(vargs);
} else {
return vargs_is_invocable_with<Function>({});
return raw_function_is_invocable_with<Function>({});
}
}
@@ -92,9 +92,9 @@ namespace meta_hpp
if constexpr ( sizeof...(Args) > 0 ) {
using namespace detail;
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{std::forward<Args>(args)}...};
return vargs_is_invocable_with<Function>(vargs);
return raw_function_is_invocable_with<Function>(vargs);
} else {
return vargs_is_invocable_with<Function>({});
return raw_function_is_invocable_with<Function>({});
}
}
}
@@ -131,14 +131,14 @@ namespace meta_hpp
bool is_invocable_with() {
using namespace detail;
const inst_base vinst{type_list<Instance>{}};
return vargs_is_invocable_with<Member>(vinst);
return raw_member_is_gettable_with<Member>(vinst);
}
template < detail::member_kind Member, typename Instance >
bool is_invocable_with(Instance&& instance) {
using namespace detail;
const inst_base vinst{std::forward<Instance>(instance)};
return vargs_is_invocable_with<Member>(vinst);
return raw_member_is_gettable_with<Member>(vinst);
}
}
@@ -150,9 +150,9 @@ namespace meta_hpp
const inst_base vinst{type_list<Instance>{}};
if constexpr ( sizeof...(Args) > 0 ) {
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
return vargs_is_invocable_with<Method>(vinst, vargs);
return raw_method_is_invocable_with<Method>(vinst, vargs);
} else {
return vargs_is_invocable_with<Method>(vinst, {});
return raw_method_is_invocable_with<Method>(vinst, {});
}
}
@@ -162,9 +162,9 @@ namespace meta_hpp
const inst_base vinst{std::forward<Instance>(instance)};
if constexpr ( sizeof...(Args) > 0 ) {
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{std::forward<Args>(args)}...};
return vargs_is_invocable_with<Method>(vinst, vargs);
return raw_method_is_invocable_with<Method>(vinst, vargs);
} else {
return vargs_is_invocable_with<Method>(vinst, {});
return raw_method_is_invocable_with<Method>(vinst, {});
}
}
}

View File

@@ -0,0 +1,67 @@
/*******************************************************************************
* 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_untests.hpp"
namespace
{
struct clazz_1 {
int i{};
clazz_1(int i) : i{i} {}
};
struct clazz_2 {
int i{};
clazz_2(int i) : i{i} {}
};
struct clazz_3 {
int i{};
clazz_3(int i) : i{i} {}
};
}
TEST_CASE("meta/meta_states/ctor") {
namespace meta = meta_hpp;
meta::class_<clazz_1>()
.ctor_<int>(meta::ctor_policy::as_object{});
meta::class_<clazz_2>()
.ctor_<int>(meta::ctor_policy::as_raw_pointer{});
meta::class_<clazz_3>()
.ctor_<int>(meta::ctor_policy::as_shared_pointer{});
SUBCASE("clazz_1") {
const meta::class_type clazz_type = meta::resolve_type<clazz_1>();
REQUIRE(clazz_type);
const meta::value v = clazz_type.create(10).value();
CHECK(v.get_type() == meta::resolve_type<clazz_1>());
CHECK(v.cast<clazz_1>().i == 10);
}
SUBCASE("clazz_2") {
const meta::class_type clazz_type = meta::resolve_type<clazz_2>();
REQUIRE(clazz_type);
const meta::value v = clazz_type.create(20).value();
CHECK(v.get_type() == meta::resolve_type<clazz_2*>());
CHECK(v.cast<clazz_2*>()->i == 20);
//TODO: dtor!!!
}
SUBCASE("clazz_3") {
const meta::class_type clazz_type = meta::resolve_type<clazz_3>();
REQUIRE(clazz_type);
const meta::value v = clazz_type.create(30).value();
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz_3>>());
CHECK(v.cast<std::shared_ptr<clazz_3>>()->i == 30);
}
}

View File

@@ -11,6 +11,7 @@ namespace
struct clazz_1 {
int int_member = 1;
const int const_int_member = 2;
std::unique_ptr<int> unique_int_member = std::make_unique<int>(42);
};
struct clazz_2 {};
@@ -21,7 +22,10 @@ TEST_CASE("meta/meta_states/member") {
meta::class_<clazz_1>()
.member_("int_member", &clazz_1::int_member)
.member_("const_int_member", &clazz_1::const_int_member);
.member_("const_int_member", &clazz_1::const_int_member)
// .member_("unique_int_member", &clazz_1::unique_int_member)
.member_("unique_int_member_as_ptr", &clazz_1::unique_int_member, meta::member_policy::as_pointer{})
.member_("unique_int_member_as_ref", &clazz_1::unique_int_member, meta::member_policy::as_reference_wrapper{});
const meta::class_type clazz_1_type = meta::resolve_type<clazz_1>();
REQUIRE(clazz_1_type);
@@ -211,4 +215,46 @@ TEST_CASE("meta/meta_states/member") {
CHECK(vm(v) == 2);
}
}
SUBCASE("unique_int_member_as_ptr") {
meta::member vm = clazz_1_type.get_member("unique_int_member_as_ptr");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::unique_int_member));
CHECK(vm.get_name() == "unique_int_member_as_ptr");
{
clazz_1 v;
CHECK(vm.get(v).get_type() == meta::resolve_type<std::unique_ptr<int>*>());
CHECK(vm.get(v) == std::addressof(v.unique_int_member));
}
{
const clazz_1 v;
CHECK(vm.get(v).get_type() == meta::resolve_type<const std::unique_ptr<int>*>());
CHECK(vm.get(v) == std::addressof(v.unique_int_member));
}
}
SUBCASE("unique_int_member_as_ref") {
meta::member vm = clazz_1_type.get_member("unique_int_member_as_ref");
REQUIRE(vm);
CHECK(vm.get_type() == meta::resolve_type(&clazz_1::unique_int_member));
CHECK(vm.get_name() == "unique_int_member_as_ref");
{
clazz_1 v;
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get(v).try_cast<ref_t>()->get() == v.unique_int_member);
}
{
const clazz_1 v;
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
CHECK(vm.get(v).get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get(v).try_cast<ref_t>()->get() == v.unique_int_member);
}
}
}

View File

@@ -14,6 +14,9 @@ namespace
static int& ref_int_variable;
static const int& const_ref_int_variable;
static std::unique_ptr<int> unique_int_variable;
static const std::unique_ptr<int> const_unique_int_variable;
};
int clazz_1::int_variable = 1;
@@ -21,6 +24,9 @@ namespace
int& clazz_1::ref_int_variable = clazz_1::int_variable;
const int& clazz_1::const_ref_int_variable = clazz_1::const_int_variable;
std::unique_ptr<int> clazz_1::unique_int_variable = std::make_unique<int>(42);
const std::unique_ptr<int> clazz_1::const_unique_int_variable = std::make_unique<int>(42);
}
TEST_CASE("meta/meta_states/variable") {
@@ -30,7 +36,15 @@ TEST_CASE("meta/meta_states/variable") {
.variable_("int_variable", &clazz_1::int_variable)
.variable_("const_int_variable", &clazz_1::const_int_variable)
.variable_("ref_int_variable", &clazz_1::ref_int_variable)
.variable_("const_ref_int_variable", &clazz_1::const_ref_int_variable);
.variable_("const_ref_int_variable", &clazz_1::const_ref_int_variable)
// .variable_("unique_int_variable", &clazz_1::unique_int_variable)
.variable_("unique_int_variable_as_ptr", &clazz_1::unique_int_variable, meta::variable_policy::as_pointer{})
.variable_("unique_int_variable_as_ref", &clazz_1::unique_int_variable, meta::variable_policy::as_reference_wrapper{})
// .variable_("const_unique_int_variable", &clazz_1::const_unique_int_variable)
.variable_("const_unique_int_variable_as_ptr", &clazz_1::const_unique_int_variable, meta::variable_policy::as_pointer{})
.variable_("const_unique_int_variable_as_ref", &clazz_1::const_unique_int_variable, meta::variable_policy::as_reference_wrapper{});
const meta::class_type clazz_1_type = meta::resolve_type<clazz_1>();
REQUIRE(clazz_1_type);
@@ -145,4 +159,76 @@ TEST_CASE("meta/meta_states/variable") {
CHECK_THROWS(vm.set(10)); CHECK(vm.get() == 2);
CHECK_THROWS(vm(11)); CHECK(vm() == 2);
}
SUBCASE("unique_int_variable_as_ptr") {
meta::variable vm = clazz_1_type.get_variable("unique_int_variable_as_ptr");
REQUIRE(vm);
CHECK(vm.get().get_type() == meta::resolve_type<std::unique_ptr<int>*>());
CHECK(vm.get() == std::addressof(clazz_1::unique_int_variable));
{
auto nv = std::make_unique<int>(11);
CHECK_NOTHROW(vm.set(std::move(nv)));
CHECK(*clazz_1::unique_int_variable == 11);
}
{
auto nv = std::make_unique<int>(12);
CHECK_THROWS(vm.set(nv));
CHECK(*clazz_1::unique_int_variable == 11);
}
}
SUBCASE("unique_int_variable_as_ref") {
meta::variable vm = clazz_1_type.get_variable("unique_int_variable_as_ref");
REQUIRE(vm);
using ref_t = std::reference_wrapper<std::unique_ptr<int>>;
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get().try_cast<ref_t>()->get() == clazz_1::unique_int_variable);
{
auto nv = std::make_unique<int>(13);
CHECK_NOTHROW(vm.set(std::move(nv)));
CHECK(*clazz_1::unique_int_variable == 13);
}
{
auto nv = std::make_unique<int>(14);
CHECK_THROWS(vm.set(nv));
CHECK(*clazz_1::unique_int_variable == 13);
}
}
SUBCASE("const_unique_int_variable_as_ptr") {
meta::variable vm = clazz_1_type.get_variable("const_unique_int_variable_as_ptr");
REQUIRE(vm);
CHECK(vm.get().get_type() == meta::resolve_type<const std::unique_ptr<int>*>());
CHECK(vm.get() == std::addressof(clazz_1::const_unique_int_variable));
{
auto nv = std::make_unique<int>(11);
CHECK_THROWS(vm.set(nv));
CHECK_THROWS(vm.set(std::move(nv)));
CHECK(*clazz_1::const_unique_int_variable == 42);
}
}
SUBCASE("const_unique_int_variable_as_ref") {
meta::variable vm = clazz_1_type.get_variable("const_unique_int_variable_as_ref");
REQUIRE(vm);
using ref_t = std::reference_wrapper<const std::unique_ptr<int>>;
CHECK(vm.get().get_type() == meta::resolve_type<ref_t>());
CHECK(vm.get().try_cast<ref_t>()->get() == clazz_1::const_unique_int_variable);
{
auto nv = std::make_unique<int>(12);
CHECK_THROWS(vm.set(nv));
CHECK_THROWS(vm.set(std::move(nv)));
CHECK(*clazz_1::const_unique_int_variable == 42);
}
}
}

View File

@@ -70,7 +70,7 @@ namespace
{\
using namespace meta::detail;\
auto function_ptr = meta::select<int(ToType)>(&FName);\
meta::function f_state{function_state::make("", function_ptr)};\
meta::function f_state{function_state::make<meta::function_policy::as_copy>("", function_ptr)};\
\
if ( std::is_invocable_v<decltype(function_ptr), decltype(FromValue)> ) {\
CHECK(arg{FromValue}.can_cast_to<ToType>());\
@@ -94,7 +94,7 @@ namespace
{\
using namespace meta::detail;\
auto function_ptr = meta::select<int(ToType)>(&FName);\
meta::function f_state{function_state::make("", function_ptr)};\
meta::function f_state{function_state::make<meta::function_policy::as_copy>("", function_ptr)};\
\
if ( std::is_invocable_v<decltype(function_ptr), FromType> ) {\
CHECK(f_state.is_invocable_with<FromType>());\

View File

@@ -30,7 +30,7 @@ namespace
{\
using namespace meta::detail;\
auto method_ptr = meta::select<int() Qualifiers>(&clazz::FName);\
meta::method m_state{method_state::make("", method_ptr)};\
meta::method m_state{method_state::make<meta::method_policy::as_copy>("", method_ptr)};\
\
if ( std::is_invocable_v<decltype(method_ptr), decltype(Inst)> ) {\
CHECK(inst{Inst}.can_cast_to<clazz Qualifiers>());\
@@ -54,7 +54,7 @@ namespace
{\
using namespace meta::detail;\
auto method_ptr = meta::select<int() ToQualifiers>(&clazz::FName);\
meta::method m_state{method_state::make("", method_ptr)};\
meta::method m_state{method_state::make<meta::method_policy::as_copy>("", method_ptr)};\
\
if ( std::is_invocable_v<decltype(method_ptr), FromType> ) {\
CHECK(m_state.is_invocable_with<FromType>());\