mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 11:40:35 +07:00
universal meta::invoke
This commit is contained in:
@@ -54,3 +54,4 @@
|
||||
#include "meta_utilities/arg.hpp"
|
||||
#include "meta_utilities/inst.hpp"
|
||||
#include "meta_utilities/value.hpp"
|
||||
#include "meta_utilities/vinvoke.hpp"
|
||||
|
||||
@@ -260,8 +260,8 @@ namespace meta_hpp
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
struct ctor_state final {
|
||||
using invoke_impl = std::function<value(std::span<arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(std::span<arg_base>)>;
|
||||
using invoke_impl = std::function<value(std::span<const arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(std::span<const arg_base>)>;
|
||||
|
||||
const ctor_index index;
|
||||
const invoke_impl invoke;
|
||||
@@ -287,8 +287,8 @@ namespace meta_hpp::detail
|
||||
};
|
||||
|
||||
struct function_state final {
|
||||
using invoke_impl = std::function<std::optional<value>(std::span<arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(std::span<arg_base>)>;
|
||||
using invoke_impl = std::function<std::optional<value>(std::span<const arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(std::span<const arg_base>)>;
|
||||
|
||||
const function_index index;
|
||||
const invoke_impl invoke;
|
||||
@@ -322,8 +322,8 @@ namespace meta_hpp::detail
|
||||
};
|
||||
|
||||
struct method_state final {
|
||||
using invoke_impl = std::function<std::optional<value>(const inst&, std::span<arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(const inst_base&, std::span<arg_base>)>;
|
||||
using invoke_impl = std::function<std::optional<value>(const inst&, std::span<const arg>)>;
|
||||
using is_invocable_with_impl = std::function<bool(const inst_base&, std::span<const arg_base>)>;
|
||||
|
||||
const method_index index;
|
||||
const invoke_impl invoke;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < class_kind Class, typename... Args >
|
||||
value raw_ctor_invoke(std::span<arg> args) {
|
||||
value vargs_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;
|
||||
@@ -35,7 +35,7 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
template < class_kind Class, typename... Args >
|
||||
bool raw_ctor_is_invocable_with(std::span<arg_base> args) {
|
||||
bool vargs_is_invocable_with(std::span<const arg_base> args) {
|
||||
using ct = ctor_traits<Class, Args...>;
|
||||
using argument_types = typename ct::argument_types;
|
||||
|
||||
@@ -55,13 +55,13 @@ namespace meta_hpp::detail
|
||||
template < class_kind Class, typename... Args >
|
||||
ctor_state::invoke_impl make_ctor_invoke() {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_ctor_invoke<Class, Args...>, _1);
|
||||
return std::bind(&vargs_invoke<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(&raw_ctor_is_invocable_with<Class, Args...>, _1);
|
||||
return std::bind(&vargs_is_invocable_with<Class, Args...>, _1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
value ctor::invoke(Args&&... args) const {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
using namespace detail;
|
||||
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(vargs);
|
||||
} else {
|
||||
return state_->invoke({});
|
||||
@@ -120,9 +120,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
bool ctor::is_invocable_with() const noexcept {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
using namespace detail;
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with({});
|
||||
@@ -131,9 +131,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
bool ctor::is_invocable_with(Args&&... args) const noexcept {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
using namespace detail;
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{std::forward<Args>(args)}...};
|
||||
return state_->is_invocable_with(vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with({});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < function_kind Function >
|
||||
std::optional<value> raw_function_invoke(Function function, std::span<arg> args) {
|
||||
std::optional<value> vargs_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;
|
||||
@@ -24,7 +24,7 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
return std::invoke([&function, &args]<std::size_t... Is>(std::index_sequence<Is...>){
|
||||
return std::invoke([function = std::move(function), &args]<std::size_t... Is>(std::index_sequence<Is...>){
|
||||
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");
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
template < function_kind Function >
|
||||
bool raw_function_is_invocable_with(std::span<arg_base> args) {
|
||||
bool vargs_is_invocable_with(std::span<const arg_base> args) {
|
||||
using ft = function_traits<Function>;
|
||||
using argument_types = typename ft::argument_types;
|
||||
|
||||
@@ -64,13 +64,13 @@ namespace meta_hpp::detail
|
||||
template < function_kind Function >
|
||||
function_state::invoke_impl make_function_invoke(Function function) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_function_invoke<Function>, function, _1);
|
||||
return std::bind(&vargs_invoke<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(&raw_function_is_invocable_with<Function>, _1);
|
||||
return std::bind(&vargs_is_invocable_with<Function>, _1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ 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(function)}
|
||||
, invoke{make_function_invoke(std::move(function))}
|
||||
, is_invocable_with{make_function_is_invocable_with<Function>()} {}
|
||||
|
||||
template < function_kind Function >
|
||||
@@ -116,9 +116,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
std::optional<value> function::invoke(Args&&... args) const {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
using namespace detail;
|
||||
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(vargs);
|
||||
} else {
|
||||
return state_->invoke({});
|
||||
@@ -132,9 +132,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
bool function::is_invocable_with() const noexcept {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
using namespace detail;
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with({});
|
||||
@@ -143,9 +143,9 @@ namespace meta_hpp
|
||||
|
||||
template < typename... Args >
|
||||
bool function::is_invocable_with(Args&&... args) const noexcept {
|
||||
using namespace detail;
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
using namespace detail;
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{std::forward<Args>(args)}...};
|
||||
return state_->is_invocable_with(vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with({});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
value raw_member_getter(Member member, const inst& inst) {
|
||||
value vargs_invoke(Member member, const inst& inst) {
|
||||
using mt = member_traits<Member>;
|
||||
using class_type = typename mt::class_type;
|
||||
using value_type = typename mt::value_type;
|
||||
@@ -25,10 +25,23 @@ namespace meta_hpp::detail
|
||||
throw std::logic_error("an attempt to get a member with an incorrect instance type");
|
||||
}
|
||||
|
||||
value_type return_value{std::invoke(member, inst.cast<qualified_type>())};
|
||||
value_type return_value{std::invoke(std::move(member), inst.cast<qualified_type>())};
|
||||
return value{std::forward<value_type>(return_value)};
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
bool vargs_is_invocable_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>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < member_kind Member >
|
||||
void raw_member_setter([[maybe_unused]] Member member, const inst& inst, const arg& arg) {
|
||||
using mt = member_traits<Member>;
|
||||
@@ -52,20 +65,10 @@ namespace meta_hpp::detail
|
||||
throw std::logic_error("an attempt to set a member with an incorrect argument type");
|
||||
}
|
||||
|
||||
std::invoke(member, inst.cast<qualified_type>()) = arg.cast<value_type>();
|
||||
std::invoke(std::move(member), inst.cast<qualified_type>()) = arg.cast<value_type>();
|
||||
}
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
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>();
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
bool raw_member_is_settable_with(const inst_base& inst, const arg_base& arg) {
|
||||
using mt = member_traits<Member>;
|
||||
@@ -86,19 +89,19 @@ namespace meta_hpp::detail
|
||||
template < member_kind Member >
|
||||
member_state::getter_impl make_member_getter(Member member) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_member_getter<Member>, member, _1);
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
member_state::setter_impl make_member_setter(Member member) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_member_setter<Member>, member, _1, _2);
|
||||
return std::bind(&vargs_invoke<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(&raw_member_is_gettable_with<Member>, _1);
|
||||
return std::bind(&vargs_is_invocable_with<Member>, _1);
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
member_state::setter_impl make_member_setter(Member member) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_member_setter<Member>, std::move(member), _1, _2);
|
||||
}
|
||||
|
||||
template < member_kind Member >
|
||||
@@ -113,8 +116,8 @@ 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(member)}
|
||||
, setter{make_member_setter(member)}
|
||||
, 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>()} {}
|
||||
|
||||
@@ -153,13 +156,16 @@ namespace meta_hpp
|
||||
template < typename Instance >
|
||||
value member::get(Instance&& instance) const {
|
||||
using namespace detail;
|
||||
return state_->getter(inst{std::forward<Instance>(instance)});
|
||||
const inst vinst{std::forward<Instance>(instance)};
|
||||
return state_->getter(vinst);
|
||||
}
|
||||
|
||||
template < typename Instance, typename Value >
|
||||
void member::set(Instance&& instance, Value&& value) const {
|
||||
using namespace detail;
|
||||
state_->setter(inst{std::forward<Instance>(instance)}, arg{std::forward<Value>(value)});
|
||||
const inst vinst{std::forward<Instance>(instance)};
|
||||
const arg vvalue{std::forward<Value>(value)};
|
||||
state_->setter(vinst, vvalue);
|
||||
}
|
||||
|
||||
template < typename Instance >
|
||||
@@ -175,24 +181,30 @@ namespace meta_hpp
|
||||
template < typename Instance >
|
||||
[[nodiscard]] bool member::is_gettable_with() const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_gettable_with(inst_base{type_list<Instance>{}});
|
||||
const inst_base vinst{type_list<Instance>{}};
|
||||
return state_->is_gettable_with(vinst);
|
||||
}
|
||||
|
||||
template < typename Instance >
|
||||
[[nodiscard]] bool member::is_gettable_with(Instance&& instance) const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_gettable_with(inst{std::forward<Instance>(instance)});
|
||||
const inst_base vinst{std::forward<Instance>(instance)};
|
||||
return state_->is_gettable_with(vinst);
|
||||
}
|
||||
|
||||
template < typename Instance, typename Value >
|
||||
[[nodiscard]] bool member::is_settable_with() const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_settable_with(inst_base{type_list<Instance>{}}, arg_base{type_list<Value>{}});
|
||||
const inst_base vinst{type_list<Instance>{}};
|
||||
const arg_base vvalue{type_list<Value>{}};
|
||||
return state_->is_settable_with(vinst, vvalue);
|
||||
}
|
||||
|
||||
template < typename Instance, typename Value >
|
||||
[[nodiscard]] bool member::is_settable_with(Instance&& instance, Value&& value) const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_settable_with(inst{std::forward<Instance>(instance)}, arg{std::forward<Value>(value)});
|
||||
const inst_base vinst{std::forward<Instance>(instance)};
|
||||
const arg_base vvalue{std::forward<Value>(value)};
|
||||
return state_->is_settable_with(vinst, vvalue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < method_kind Method >
|
||||
std::optional<value> raw_method_invoke(Method method, const inst& inst, std::span<arg> args) {
|
||||
std::optional<value> vargs_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;
|
||||
@@ -29,7 +29,7 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
return std::invoke([&method, &inst, &args]<std::size_t... Is>(std::index_sequence<Is...>){
|
||||
return std::invoke([method = std::move(method), &inst, &args]<std::size_t... Is>(std::index_sequence<Is...>){
|
||||
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");
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
template < method_kind Method >
|
||||
bool raw_method_is_invocable_with(const inst_base& inst, std::span<arg_base> args) {
|
||||
bool vargs_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;
|
||||
@@ -76,13 +76,13 @@ namespace meta_hpp::detail
|
||||
template < method_kind Method >
|
||||
method_state::invoke_impl make_method_invoke(Method method) {
|
||||
using namespace std::placeholders;
|
||||
return std::bind(&raw_method_invoke<Method>, method, _1, _2);
|
||||
return std::bind(&vargs_invoke<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(&raw_method_is_invocable_with<Method>, _1, _2);
|
||||
return std::bind(&vargs_is_invocable_with<Method>, _1, _2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ 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(method)}
|
||||
, invoke{make_method_invoke(std::move(method))}
|
||||
, is_invocable_with{make_method_is_invocable_with<Method>()} {}
|
||||
|
||||
template < method_kind Method >
|
||||
@@ -129,11 +129,12 @@ namespace meta_hpp
|
||||
template < typename Instance, typename... Args >
|
||||
std::optional<value> method::invoke(Instance&& instance, Args&&... args) const {
|
||||
using namespace detail;
|
||||
const inst vinst{std::forward<Instance>(instance)};
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(inst{std::forward<Instance>(instance)}, vargs);
|
||||
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
return state_->invoke(vinst, vargs);
|
||||
} else {
|
||||
return state_->invoke(inst{std::forward<Instance>(instance)}, {});
|
||||
return state_->invoke(vinst, {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,22 +146,24 @@ namespace meta_hpp
|
||||
template < typename Instance, typename... Args >
|
||||
bool method::is_invocable_with() const noexcept {
|
||||
using namespace detail;
|
||||
const inst_base vinst{type_list<Instance>{}};
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(inst_base{type_list<Instance>{}}, vargs);
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{type_list<Args>{}}...};
|
||||
return state_->is_invocable_with(vinst, vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with(inst_base{type_list<Instance>{}}, {});
|
||||
return state_->is_invocable_with(vinst, {});
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Instance, typename... Args >
|
||||
bool method::is_invocable_with(Instance&& instance, Args&&... args) const noexcept {
|
||||
using namespace detail;
|
||||
const inst_base vinst{std::forward<Instance>(instance)};
|
||||
if constexpr ( sizeof...(Args) > 0 ) {
|
||||
std::array<arg_base, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
|
||||
return state_->is_invocable_with(inst{std::forward<Instance>(instance)}, vargs);
|
||||
const std::array<arg_base, sizeof...(Args)> vargs{arg_base{std::forward<Args>(args)}...};
|
||||
return state_->is_invocable_with(vinst, vargs);
|
||||
} else {
|
||||
return state_->is_invocable_with(inst{std::forward<Instance>(instance)}, {});
|
||||
return state_->is_invocable_with(vinst, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,8 @@ namespace meta_hpp
|
||||
template < typename Value >
|
||||
void variable::set(Value&& value) const {
|
||||
using namespace detail;
|
||||
state_->setter(arg{std::forward<Value>(value)});
|
||||
const arg vvalue{std::forward<Value>(value)};
|
||||
state_->setter(vvalue);
|
||||
}
|
||||
|
||||
inline value variable::operator()() const {
|
||||
@@ -132,12 +133,14 @@ namespace meta_hpp
|
||||
template < typename Value >
|
||||
bool variable::is_settable_with() const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_settable_with(arg_base{type_list<Value>{}});
|
||||
const arg_base vvalue{type_list<Value>{}};
|
||||
return state_->is_settable_with(vvalue);
|
||||
}
|
||||
|
||||
template < typename Value >
|
||||
bool variable::is_settable_with(Value&& value) const noexcept {
|
||||
using namespace detail;
|
||||
return state_->is_settable_with(arg{std::forward<Value>(value)});
|
||||
const arg vvalue{std::forward<Value>(value)};
|
||||
return state_->is_settable_with(vvalue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +236,12 @@ namespace meta_hpp::detail
|
||||
|
||||
virtual ~arg_base() = default;
|
||||
|
||||
template < decay_value_kind T >
|
||||
explicit arg_base(T&& v);
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
explicit arg_base(T&& v);
|
||||
|
||||
template < arg_lvalue_ref_kind T >
|
||||
requires decay_non_uvalue_kind<T>
|
||||
explicit arg_base(type_list<T>);
|
||||
@@ -313,6 +319,12 @@ namespace meta_hpp::detail
|
||||
|
||||
virtual ~inst_base() = default;
|
||||
|
||||
template < decay_value_kind T >
|
||||
explicit inst_base(T&& v);
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
explicit inst_base(T&& v);
|
||||
|
||||
template < inst_class_lvalue_ref_kind T >
|
||||
explicit inst_base(type_list<T>);
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < decay_value_kind T >
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
arg_base::arg_base(T&&)
|
||||
: arg_base{type_list<T&&>{}} {}
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
arg_base::arg_base(T&&)
|
||||
: arg_base{type_list<T&&>{}} {}
|
||||
|
||||
template < arg_lvalue_ref_kind T >
|
||||
requires decay_non_uvalue_kind<T>
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
@@ -174,7 +184,7 @@ namespace meta_hpp::detail
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
arg::arg(T&& v)
|
||||
: arg_base{type_list<T&&>{}}
|
||||
: arg_base{std::forward<T>(v)}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
, data_{const_cast<std::remove_cvref_t<T>*>(std::addressof(v))} {}
|
||||
|
||||
|
||||
@@ -62,6 +62,16 @@ namespace meta_hpp::detail
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < decay_value_kind T >
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
inst_base::inst_base(T&&)
|
||||
: inst_base{type_list<T&&>{}} {}
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
inst_base::inst_base(T&&)
|
||||
: inst_base{type_list<T&&>{}} {}
|
||||
|
||||
template < inst_class_lvalue_ref_kind T >
|
||||
// NOLINTNEXTLINE(readability-named-parameter)
|
||||
inst_base::inst_base(type_list<T>)
|
||||
@@ -174,7 +184,7 @@ namespace meta_hpp::detail
|
||||
|
||||
template < decay_non_uvalue_kind T >
|
||||
inst::inst(T&& v)
|
||||
: inst_base{type_list<T&&>{}}
|
||||
: inst_base{std::forward<T>(v)}
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
|
||||
, data_{const_cast<std::remove_cvref_t<T>*>(std::addressof(v))} {}
|
||||
|
||||
|
||||
170
headers/meta.hpp/meta_utilities/vinvoke.hpp
Normal file
170
headers/meta.hpp/meta_utilities/vinvoke.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../meta_base.hpp"
|
||||
#include "../meta_states.hpp"
|
||||
#include "../meta_utilities.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename... Args >
|
||||
std::optional<value> invoke(const function& function, Args&&... args) {
|
||||
return function.invoke(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < detail::function_kind Function, typename... Args >
|
||||
std::optional<value> invoke(Function&& function, Args&&... args) {
|
||||
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);
|
||||
} else {
|
||||
return vargs_invoke(std::forward<Function>(function), {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Instance >
|
||||
std::optional<value> invoke(const member& member, Instance&& instance) {
|
||||
return member.get(std::forward<Instance>(instance));
|
||||
}
|
||||
|
||||
template < detail::member_kind Member, typename Instance >
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Instance, typename... Args >
|
||||
std::optional<value> invoke(const method& method, Instance&& instance, Args&&... args) {
|
||||
return method.invoke(std::forward<Instance>(instance), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < detail::method_kind Method, typename Instance, typename... Args >
|
||||
std::optional<value> invoke(Method&& method, Instance&& instance, Args&&... args) {
|
||||
using namespace detail;
|
||||
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);
|
||||
} else {
|
||||
return vargs_invoke(std::forward<Method>(method), vinst, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename... Args >
|
||||
bool is_invocable_with(const function& function) {
|
||||
return function.is_invocable_with<Args...>();
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
bool is_invocable_with(const function& function, Args&&... args) {
|
||||
return function.is_invocable_with(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template < detail::function_kind Function, typename... Args >
|
||||
bool is_invocable_with() {
|
||||
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);
|
||||
} else {
|
||||
return vargs_is_invocable_with<Function>({});
|
||||
}
|
||||
}
|
||||
|
||||
template < detail::function_kind Function, typename... Args >
|
||||
bool is_invocable_with(Args&&... args) {
|
||||
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);
|
||||
} else {
|
||||
return vargs_is_invocable_with<Function>({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Instance >
|
||||
bool is_invocable_with(const member& member) {
|
||||
return member.is_gettable_with<Instance>();
|
||||
}
|
||||
|
||||
template < typename Instance >
|
||||
bool is_invocable_with(const member& member, Instance&& instance) {
|
||||
return member.is_gettable_with(std::forward<Instance>(instance));
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Instance, typename... Args >
|
||||
bool is_invocable_with(const method& method) {
|
||||
return method.is_invocable_with<Instance, Args...>();
|
||||
}
|
||||
|
||||
template < typename Instance, typename... Args >
|
||||
bool is_invocable_with(const method& method, Instance&& instance, Args&&... args) {
|
||||
return method.is_invocable_with(std::forward<Instance>(instance), std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < detail::member_kind Member, typename Instance >
|
||||
bool is_invocable_with() {
|
||||
using namespace detail;
|
||||
const inst_base vinst{type_list<Instance>{}};
|
||||
return vargs_is_invocable_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);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < detail::method_kind Method, typename Instance, typename... Args >
|
||||
bool is_invocable_with() {
|
||||
using namespace detail;
|
||||
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);
|
||||
} else {
|
||||
return vargs_is_invocable_with<Method>(vinst, {});
|
||||
}
|
||||
}
|
||||
|
||||
template < detail::method_kind Method, typename Instance, typename... Args >
|
||||
bool is_invocable_with(Instance&& instance, Args&&... args) {
|
||||
using namespace detail;
|
||||
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);
|
||||
} else {
|
||||
return vargs_is_invocable_with<Method>(vinst, {});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user