5#define SYS_VM_HAS_MEMBER(ARG, NAME) \
6 sysio::vm::detail::overloaded { \
7 [](auto&& f, std::enable_if_t<std::is_class_v<std::decay_t<decltype(f)>> && \
8 sysio::vm::detail::pass_type< \
9 decltype(&std::decay_t<decltype(f)>::type::NAME)>(), int> = 0) constexpr { \
11 }, [](...) constexpr { return false; } \
12 }(sysio::vm::detail::wrapper_t<decltype(ARG)>{})
14#define SYS_VM_HAS_MEMBER_TY(TY, NAME) \
15 sysio::vm::detail::overloaded { \
16 [](auto&& f, std::enable_if_t<std::is_class_v<TY> && \
17 sysio::vm::detail::pass_type< \
18 decltype(&std::decay_t<decltype(f)>::type::NAME)>(), int> = 0) constexpr { \
20 }, [](...) constexpr { return false; } \
21 }(sysio::vm::detail::wrapper_t<TY>{})
23#define SYS_VM_HAS_TEMPLATE_MEMBER(ARG, NAME) \
24 sysio::vm::detail::overloaded { \
25 [&](auto&& f, std::enable_if_t<std::is_class_v<std::decay_t<decltype(f)>> && \
26 sysio::vm::detail::pass_type< \
27 decltype(&std::decay_t<decltype(f)>::type::template NAME)>(), int> = 0) constexpr { \
29 }, [](...) constexpr { return false; } \
30 }(sysio::vm::detail::wrapper_t<decltype(ARG)>{})
32#define SYS_VM_HAS_TEMPLATE_MEMBER_TY(TY, NAME) \
33 sysio::vm::detail::overloaded { \
34 [](auto&& f, std::enable_if_t<std::is_class_v<TY> && \
35 sysio::vm::detail::pass_type< \
36 decltype(&std::decay_t<decltype(f)>::type::template NAME)>(), int> = 0) constexpr { \
38 }, [](...) constexpr { return false; } \
39 }(sysio::vm::detail::wrapper_t<TY>{})
46#define AUTO_PARAM_WORKAROUND(X) sysio::vm::detail::make_dependent<decltype(X)>(X)
48namespace sysio {
namespace vm {
54 constexpr bool pass_type() {
return true; }
61 template<
class... Ts>
struct overloaded : Ts... {
using Ts::operator()...; };
71 template <
typename T,
typename U>
82 template <
bool Decay,
typename R,
typename... Args>
83 constexpr auto get_types(
R(Args...)) -> std::tuple<
R, freestanding,
84 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
85 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
86 constexpr auto get_types(
R (Cls::*)(Args...)) -> std::tuple<
R, Cls,
87 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
88 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
89 constexpr auto get_types(
R (Cls::*)(Args...)const) -> std::tuple<
R, Cls,
90 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
91 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
92 constexpr auto get_types(
R (Cls::*)(Args...)&) -> std::tuple<
R, Cls,
93 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
94 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
95 constexpr auto get_types(
R (Cls::*)(Args...)&&) -> std::tuple<
R, Cls,
96 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
97 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
98 constexpr auto get_types(
R (Cls::*)(Args...)const &) -> std::tuple<
R, Cls,
99 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
100 template <
bool Decay,
typename R,
typename Cls,
typename... Args>
101 constexpr auto get_types(
R (Cls::*)(Args...)const &&) -> std::tuple<
R, Cls,
102 std::tuple<std::conditional_t<Decay, std::decay_t<Args>, Args>...>>;
103 template <
bool Decay,
typename F>
105 if constexpr (is_callable_v<
decltype(
fn)>)
111 template <
bool Decay,
typename F>
114 template <std::size_t Sz, std::size_t
N, std::size_t I,
typename... Args>
117 template <std::size_t Sz, std::size_t
N, std::size_t I,
typename Arg,
typename... Args>
119 static_assert(Sz >
N,
"index out of range");
123 template <std::size_t Sz, std::size_t
N,
typename Arg,
typename... Args>
125 using type = std::tuple<Arg, Args...>;
128 template <std::size_t
N,
typename... Args>
131 template <std::size_t
N,
typename R,
typename... Args>
133 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
135 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
137 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
139 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
141 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
143 template <std::size_t
N,
typename R,
typename Cls,
typename... Args>
145 template <std::
size_t N,
typename F>
147 if constexpr (is_callable_v<
decltype(fn)>)
153 template <std::
size_t N,
typename F>
157 template <
typename R,
typename... Args>
158 constexpr bool is_function(
R(*)(Args...)) {
return true; }
160 template <
typename F>
163 template <
typename R,
typename Cls,
typename... Args>
166 template <
typename R,
typename Cls,
typename... Args>
169 template <
typename R,
typename Cls,
typename... Args>
172 template <
typename R,
typename Cls,
typename... Args>
175 template <
typename R,
typename Cls,
typename... Args>
178 template <
typename R,
typename Cls,
typename... Args>
181 template <
typename F>
190 template <
typename F>
191 constexpr bool is_class(F&&) {
return std::is_class_v<F>; }
193 template <
typename F>
194 constexpr auto return_type(F&& fn) -> std::tuple_element_t<0, detail::get_types_t<false, F>>;
199 template <
typename F>
200 constexpr auto class_from_member(F&& fn) -> std::tuple_element_t<1, detail::get_types_t<false, F>>;
205 template <
typename F>
206 constexpr auto flatten_parameters(F&& fn) -> std::tuple_element_t<2, detail::get_types_t<false, F>>;
211 template <
typename F>
217 template <std::
size_t N,
typename F>
218 constexpr auto parameter_at(F&& fn) -> std::tuple_element_t<
N,
221 template <std::
size_t N, auto FN>
224 template <std::
size_t N,
typename F>
227 template <std::
size_t N, auto FN>
230 template <
typename F>
231 inline constexpr static std::size_t arity(F&& fn) {
return std::tuple_size_v<
decltype(
flatten_parameters(fn))>; }
234 inline constexpr static std::size_t arity_v = arity(FN);
overloaded(Ts...) -> overloaded< Ts... >
decltype(parameters_from_impl< N >(std::declval< F >())) parameters_from_impl_t
constexpr U && make_dependent(U &&u)
constexpr auto parameters_from_impl(R(Args...)) -> pack_from_t< N, Args... >
typename pack_from< sizeof...(Args), N, 0, Args... >::type pack_from_t
constexpr bool pass_type()
constexpr auto get_types(R(Args...)) -> std::tuple< R, freestanding, std::tuple< std::conditional_t< Decay, std::decay_t< Args >, Args >... > >
constexpr bool is_callable_impl(...)
decltype(get_types< Decay >(std::declval< F >())) get_types_t
decltype(return_type(AUTO_PARAM_WORKAROUND(FN))) return_type_t
constexpr auto parameters_from(F &&fn) -> detail::parameters_from_impl_t< N, F >
constexpr bool is_class(F &&)
decltype(parameter_at< N >(AUTO_PARAM_WORKAROUND(FN))) parameter_at_t
decltype(decayed_flatten_parameters(AUTO_PARAM_WORKAROUND(FN))) decayed_flatten_parameters_t
decltype(parameters_from< N >(AUTO_PARAM_WORKAROUND(FN))) parameters_from_t
decltype(class_from_member(AUTO_PARAM_WORKAROUND(FN))) class_from_member_t
constexpr bool is_function(R(*)(Args...))
constexpr auto return_type(F &&fn) -> std::tuple_element_t< 0, detail::get_types_t< false, F > >
decltype(flatten_parameters(AUTO_PARAM_WORKAROUND(FN))) flatten_parameters_t
constexpr auto decayed_flatten_parameters(F &&fn) -> std::tuple_element_t< 2, detail::get_types_t< true, F > >
constexpr auto parameter_at(F &&fn) -> std::tuple_element_t< N, decltype(flatten_parameters(std::declval< F >()))>
constexpr bool is_callable(F &&fn)
constexpr auto flatten_parameters(F &&fn) -> std::tuple_element_t< 2, detail::get_types_t< false, F > >
constexpr auto class_from_member(F &&fn) -> std::tuple_element_t< 1, detail::get_types_t< false, F > >
constexpr bool is_member_function(R(Cls::*)(Args...))
#define T(meth, val, expected)
typename pack_from< Sz, N, I+1, Args... >::type type
std::tuple< Arg, Args... > type
constexpr wrapper_t(T &&)
#define SYS_VM_HAS_MEMBER(ARG, NAME)
#define AUTO_PARAM_WORKAROUND(X)