Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
function_traits.hpp
Go to the documentation of this file.
1#pragma once
2#include <type_traits>
3#include <tuple>
4
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 { \
10 return true; \
11 }, [](...) constexpr { return false; } \
12 }(sysio::vm::detail::wrapper_t<decltype(ARG)>{})
13
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 { \
19 return true; \
20 }, [](...) constexpr { return false; } \
21 }(sysio::vm::detail::wrapper_t<TY>{})
22
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 { \
28 return true; \
29 }, [](...) constexpr { return false; } \
30 }(sysio::vm::detail::wrapper_t<decltype(ARG)>{})
31
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 { \
37 return true; \
38 }, [](...) constexpr { return false; } \
39 }(sysio::vm::detail::wrapper_t<TY>{})
40
41
42// Workaround for compiler bug handling C++g17 auto template parameters.
43// The parameter is not treated as being type-dependent in all contexts,
44// causing early evaluation of the containing expression.
45// Tested at Apple LLVM version 10.0.1 (clang-1001.0.46.4)
46#define AUTO_PARAM_WORKAROUND(X) sysio::vm::detail::make_dependent<decltype(X)>(X)
47
48namespace sysio { namespace vm {
49
50 struct freestanding {};
51
52 namespace detail {
53 template <typename T>
54 constexpr bool pass_type() { return true; }
55
56 template <typename>
57 constexpr bool is_callable_impl(...) {
58 return false;
59 }
60
61 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
62 template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
63
64 template <typename T>
65 struct wrapper_t {
66 using type = T;
67 constexpr wrapper_t() {}
68 constexpr wrapper_t(T&&) {}
69 };
70
71 template <typename T, typename U>
72 inline constexpr U&& make_dependent(U&& u) { return static_cast<U&&>(u); }
73 }
74
75 template <auto FN>
76 inline constexpr static bool is_callable_v = SYS_VM_HAS_MEMBER(AUTO_PARAM_WORKAROUND(FN), operator());
77
78 template <typename F>
79 constexpr bool is_callable(F&& fn) { return SYS_VM_HAS_MEMBER(fn, operator()); }
80
81 namespace detail {
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>
104 constexpr auto get_types(F&& fn) {
105 if constexpr (is_callable_v<decltype(fn)>)
106 return get_types<Decay>(&F::operator());
107 else
108 return get_types<Decay>(fn);
109 }
110
111 template <bool Decay, typename F>
112 using get_types_t = decltype(get_types<Decay>(std::declval<F>()));
113
114 template <std::size_t Sz, std::size_t N, std::size_t I, typename... Args>
115 struct pack_from;
116
117 template <std::size_t Sz, std::size_t N, std::size_t I, typename Arg, typename... Args>
118 struct pack_from<Sz, N, I, Arg, Args...> {
119 static_assert(Sz > N, "index out of range");
120 using type = typename pack_from<Sz, N, I+1, Args...>::type;
121 };
122
123 template <std::size_t Sz, std::size_t N, typename Arg, typename... Args>
124 struct pack_from<Sz, N, N, Arg, Args...> {
125 using type = std::tuple<Arg, Args...>;
126 };
127
128 template <std::size_t N, typename... Args>
129 using pack_from_t = typename pack_from<sizeof...(Args), N, 0, Args...>::type;
130
131 template <std::size_t N, typename R, typename... Args>
132 constexpr auto parameters_from_impl(R(Args...)) -> pack_from_t<N, Args...>;
133 template <std::size_t N, typename R, typename Cls, typename... Args>
134 constexpr auto parameters_from_impl(R(Cls::*)(Args...)) -> pack_from_t<N, Args...>;
135 template <std::size_t N, typename R, typename Cls, typename... Args>
136 constexpr auto parameters_from_impl(R(Cls::*)(Args...)const) -> pack_from_t<N, Args...>;
137 template <std::size_t N, typename R, typename Cls, typename... Args>
138 constexpr auto parameters_from_impl(R(Cls::*)(Args...)&) -> pack_from_t<N, Args...>;
139 template <std::size_t N, typename R, typename Cls, typename... Args>
140 constexpr auto parameters_from_impl(R(Cls::*)(Args...)&&) -> pack_from_t<N, Args...>;
141 template <std::size_t N, typename R, typename Cls, typename... Args>
142 constexpr auto parameters_from_impl(R(Cls::*)(Args...)const &) -> pack_from_t<N, Args...>;
143 template <std::size_t N, typename R, typename Cls, typename... Args>
144 constexpr auto parameters_from_impl(R(Cls::*)(Args...)const &&) -> pack_from_t<N, Args...>;
145 template <std::size_t N, typename F>
146 constexpr auto parameters_from_impl(F&& fn) {
147 if constexpr (is_callable_v<decltype(fn)>)
148 return parameters_from_impl<N>(&F::operator());
149 else
150 return parameters_from_impl<N>(fn);
151 }
152
153 template <std::size_t N, typename F>
154 using parameters_from_impl_t = decltype(parameters_from_impl<N>(std::declval<F>()));
155 } // ns sysio::vm::detail
156
157 template <typename R, typename... Args>
158 constexpr bool is_function(R(*)(Args...)) { return true; }
159
160 template <typename F>
161 constexpr bool is_function(F&&) { return false; }
162
163 template <typename R, typename Cls, typename... Args>
164 constexpr bool is_member_function(R(Cls::*)(Args...)) { return true; }
165
166 template <typename R, typename Cls, typename... Args>
167 constexpr bool is_member_function(R(Cls::*)(Args...)const ) { return true; }
168
169 template <typename R, typename Cls, typename... Args>
170 constexpr bool is_member_function(R(Cls::*)(Args...)& ) { return true; }
171
172 template <typename R, typename Cls, typename... Args>
173 constexpr bool is_member_function(R(Cls::*)(Args...)&& ) { return true; }
174
175 template <typename R, typename Cls, typename... Args>
176 constexpr bool is_member_function(R(Cls::*)(Args...)const & ) { return true; }
177
178 template <typename R, typename Cls, typename... Args>
179 constexpr bool is_member_function(R(Cls::*)(Args...)const && ) { return true; }
180
181 template <typename F>
182 constexpr bool is_member_function(F&&) { return false; }
183
184 template <auto FN>
185 inline constexpr static bool is_function_v = is_function(AUTO_PARAM_WORKAROUND(FN));
186
187 template <auto FN>
188 inline constexpr static bool is_member_function_v = is_member_function(AUTO_PARAM_WORKAROUND(FN));
189
190 template <typename F>
191 constexpr bool is_class(F&&) { return std::is_class_v<F>; }
192
193 template <typename F>
194 constexpr auto return_type(F&& fn) -> std::tuple_element_t<0, detail::get_types_t<false, F>>;
195
196 template <auto FN>
197 using return_type_t = decltype(return_type(AUTO_PARAM_WORKAROUND(FN)));
198
199 template <typename F>
200 constexpr auto class_from_member(F&& fn) -> std::tuple_element_t<1, detail::get_types_t<false, F>>;
201
202 template <auto FN>
204
205 template <typename F>
206 constexpr auto flatten_parameters(F&& fn) -> std::tuple_element_t<2, detail::get_types_t<false, F>>;
207
208 template <auto FN>
210
211 template <typename F>
212 constexpr auto decayed_flatten_parameters(F&& fn) -> std::tuple_element_t<2, detail::get_types_t<true, F>>;
213
214 template <auto FN>
216
217 template <std::size_t N, typename F>
218 constexpr auto parameter_at(F&& fn) -> std::tuple_element_t<N,
219 decltype(flatten_parameters(std::declval<F>()))>;
220
221 template <std::size_t N, auto FN>
223
224 template <std::size_t N, typename F>
226
227 template <std::size_t N, auto FN>
229
230 template <typename F>
231 inline constexpr static std::size_t arity(F&& fn) { return std::tuple_size_v<decltype(flatten_parameters(fn))>; }
232
233 template <auto FN>
234 inline constexpr static std::size_t arity_v = arity(FN);
235}}
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)
const int N
Definition quantize.cpp:54
typename pack_from< Sz, N, I+1, Args... >::type type
#define R
#define SYS_VM_HAS_MEMBER(ARG, NAME)
#define AUTO_PARAM_WORKAROUND(X)
Definition dtoa.c:306
yh_object_type type
Definition yubihsm.h:672