mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 19:41:29 +07:00
add value return policy
This commit is contained in:
@@ -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
|
||||
|
||||
3
TODO.md
3
TODO.md
@@ -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?
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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...>()},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>()},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>()},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>()},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>()},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
67
untests/meta_states/ctor_tests.cpp
Normal file
67
untests/meta_states/ctor_tests.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>());\
|
||||
|
||||
@@ -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>());\
|
||||
|
||||
Reference in New Issue
Block a user