functional.hpp
Go to the documentation of this file.
1 
14 #ifndef CORE_FUNCTIONAL_HPP
15 #define CORE_FUNCTIONAL_HPP
16 
17 #include <functional>
18 #include <tuple>
19 #include <array>
20 
21 #include "type_traits.hpp"
22 #include "utility.hpp"
23 
24 namespace core {
25 inline namespace v2 {
26 
27 template <class T> using is_reference_wrapper = meta::is_specialization_of<
28  remove_cv_t<T>,
29  ::std::reference_wrapper
30 >;
31 
32 template <class F> struct function_traits;
33 
34 template <class R, class... Args>
35 struct function_traits<R(*)(Args...)> : function_traits<R(Args...)> { };
36 
37 template <class C, class R>
38 struct function_traits<R(C::*)> : function_traits<R(C&)> { };
39 
40 template <class C, class R, class... Args>
41 struct function_traits<R(C::*)(Args...)> : function_traits<R(C&, Args...)> { };
42 
43 template <class C, class R, class... Args>
44 struct function_traits<R(C::*)(Args...) const volatile> :
45  function_traits<R(C volatile const&, Args...)>
46 { };
47 
48 template <class C, class R, class... Args>
49 struct function_traits<R(C::*)(Args...) volatile> :
50  function_traits<R(C volatile&, Args...)>
51 { };
52 
53 template <class C, class R, class... Args>
54 struct function_traits<R(C::*)(Args...) const> :
55  function_traits<R(C const&, Args...)>
56 { };
57 
58 template <class R, class... Args>
59 struct function_traits<R(Args...)> {
60  using typelist = meta::list<Args...>;
61  using return_type = R;
62 
63  using pointer = add_pointer_t<return_type(Args...)>;
64  static constexpr auto arity = typelist::size();
65 
66  template <::std::size_t N> using argument = meta::get<typelist, N>;
67 };
68 
69 template <class F> struct function_traits {
72  using pointer = typename functor_type::pointer;
73  static constexpr auto arity = functor_type::arity - 1;
74  template <::std::size_t N>
75  using argument = typename functor_type::template argument<N>;
76 };
77 
78 /* N3727 */
79 template <class Functor, class... Args>
80 auto invoke (Functor&& f, Args&&... args) -> enable_if_t<
81  ::std::is_member_pointer<decay_t<Functor>>::value,
82  result_of_t<Functor&&(Args&&...)>
83 > { return ::std::mem_fn(f)(core::forward<Args>(args)...); }
84 
85 template <class Functor, class... Args>
86 auto invoke (Functor&& f, Args&&... args) -> enable_if_t<
87  not ::std::is_member_pointer<decay_t<Functor>>::value,
88  result_of_t<Functor&&(Args&&...)>
89 > { return core::forward<Functor>(f)(core::forward<Args>(args)...); }
90 
91 template <class F, class T, ::std::size_t... I>
92 auto apply (F&& f, T&& t, index_sequence<I...>) -> decltype(
93  invoke(core::forward<F>(f), ::std::get<I>(core::forward<T>(t))...)
94 ) { return invoke(core::forward<F>(f), ::std::get<I>(core::forward<T>(t))...); }
95 
96 template <
97  class Functor,
98  class T,
100 > auto apply (Functor&& f, T&& t) -> decltype(
101  apply(core::forward<Functor>(f), core::forward<T>(t), I { })
102 ) { return apply(core::forward<Functor>(f), core::forward<T>(t), I { }); }
103 
104 template <class F>
106  template <class G>
107  explicit apply_functor (G&& g) : f(core::forward<G>(g)) { }
108 
109  template <class Applicable>
110  auto operator () (Applicable&& args) -> decltype(
111  core::apply(core::forward<F>(this->f), core::forward<Applicable>(args))
112  ) { return apply(core::forward<F>(f), core::forward<Applicable>(args)); }
113 private:
114  F f;
115 };
116 
117 template <class F>
118 auto make_apply (F&& f) -> apply_functor<F> {
119  return apply_functor<F> { core::forward<F>(f) };
120 }
121 
122 template <class F>
124  template <class G>
125  explicit not_fn_functor (G&& g) : f(core::forward<G>(g)) { }
126 
127  template <class... Args>
128  auto operator () (Args&&... args) const -> decltype(
129  not (invoke)(::std::declval<F>(), core::forward<Args>(args)...)
130  ) { return not (invoke)(f, core::forward<Args>(args)...); }
131 
132  template <class... Args>
133  auto operator () (Args&&... args) -> decltype(
134  not (invoke)(::std::declval<F>(), core::forward<Args>(args)...)
135  ) { return not (invoke)(f, core::forward<Args>(args)...); }
136 
137 private:
138  F f;
139 };
140 
141 /* Were this C++14, we could just use a lambda with a capture. Oh Well! */
142 template <class F>
144  return not_fn_functor<decay_t<F>> { core::forward<F>(f) };
145 }
146 
147 /* converter function object */
148 template <class T>
149 struct converter {
150  template <class... Args>
151  constexpr T operator () (Args&&... args) const {
152  return T(core::forward<Args>(args)...);
153  }
154 };
155 
156 /* function objects -- arithmetic */
157 template <class T=void>
158 struct plus {
159  constexpr T operator () (T const& l, T const& r) const { return l + r; }
160 };
161 
162 template <class T=void>
163 struct minus {
164  constexpr T operator () (T const& l, T const& r) const { return l - r; }
165 };
166 
167 template <class T=void>
168 struct multiplies {
169  constexpr T operator () (T const& l, T const& r) const { return l * r; }
170 };
171 
172 template <class T=void>
173 struct divides {
174  constexpr T operator () (T const& l, T const& r) const { return l / r; }
175 };
176 
177 template <class T=void>
178 struct modulus {
179  constexpr T operator () (T const& l, T const& r) const { return l % r; }
180 };
181 
182 template <class T=void>
183 struct negate {
184  constexpr T operator () (T const& arg) const { return -arg; }
185 };
186 
187 /* function objects -- comparisons */
188 template <class T=void>
189 struct equal_to {
190  constexpr bool operator () (T const& l, T const& r) const { return l == r; }
191 };
192 
193 template <class T=void>
194 struct not_equal_to {
195  constexpr bool operator () (T const& l, T const& r) const { return l != r; }
196 };
197 
198 template <class T=void>
200  constexpr bool operator () (T const& l, T const& r) const { return l >= r; }
201 };
202 
203 template <class T=void>
204 struct less_equal {
205  constexpr bool operator () (T const& l, T const& r) const { return l <= r; }
206 };
207 
208 template <class T=void>
209 struct greater {
210  constexpr bool operator () (T const& l, T const& r) const { return l > r; }
211 };
212 
213 template <class T=void>
214 struct less {
215  constexpr bool operator () (T const& l, T const& r) const { return l < r; }
216 };
217 
218 /* function objects -- logical */
219 template <class T=void>
220 struct logical_and {
221  constexpr bool operator () (T const& l, T const& r) const { return l and r; }
222 };
223 
224 template <class T=void>
225 struct logical_or {
226  constexpr bool operator () (T const& l, T const& r) const { return l or r; }
227 };
228 
229 template <class T=void>
230 struct logical_not {
231  constexpr bool operator () (T const& arg) const { return not arg; }
232 };
233 
234 /* function objects -- bitwise */
235 
236 template <class T=void>
237 struct bit_and {
238  constexpr bool operator () (T const& l, T const& r) const { return l & r; }
239 };
240 
241 template <class T=void>
242 struct bit_or {
243  constexpr bool operator () (T const& l, T const& r) const { return l | r; }
244 };
245 
246 template <class T=void>
247 struct bit_xor {
248  constexpr bool operator () (T const& l, T const& r) const { return l ^ r; }
249 };
250 
251 template <class T=void>
252 struct bit_not {
253  constexpr bool operator () (T const& arg) const { return ~arg; }
254 };
255 
256 /* function objects -- arithmetic specializations */
257 template <> struct plus<void> {
258  using is_transparent = void;
259 
260  template <class T, class U>
261  constexpr auto operator () (T&& t, U&& u) const -> decltype(
262  core::forward<T>(t) + core::forward<U>(u)
263  ) { return core::forward<T>(t) + core::forward<U>(u); }
264 };
265 
266 template <> struct minus<void> {
267  using is_transparent = void;
268 
269  template <class T, class U>
270  constexpr auto operator () (T&& t, U&& u) const -> decltype(
271  core::forward<T>(t) - core::forward<U>(u)
272  ) { return core::forward<T>(t) - core::forward<U>(u); }
273 };
274 
275 template <> struct multiplies<void> {
276  using is_transparent = void;
277 
278  template <class T, class U>
279  constexpr auto operator () (T&& t, U&& u) const -> decltype(
280  core::forward<T>(t) * core::forward<U>(u)
281  ) { return core::forward<T>(t) * core::forward<U>(u); }
282 };
283 
284 template <> struct divides<void> {
285  using is_transparent = void;
286 
287  template <class T, class U>
288  constexpr auto operator () (T&& t, U&& u) const -> decltype(
289  core::forward<T>(t) / core::forward<U>(u)
290  ) { return core::forward<T>(t) / core::forward<U>(u); }
291 };
292 
293 template <> struct modulus<void> {
294  using is_transparent = void;
295 
296  template <class T, class U>
297  constexpr auto operator () (T&& t, U&& u) const -> decltype(
298  core::forward<T>(t) % core::forward<U>(u)
299  ) { return core::forward<T>(t) % core::forward<U>(u); }
300 };
301 
302 template <> struct negate<void> {
303  using is_transparent = void;
304 
305  template <class T>
306  constexpr auto operator () (T&& t) const -> decltype(core::forward<T>(t)) {
307  return core::forward<T>(t);
308  }
309 };
310 
311 /* function objects -- comparison specialization */
312 template <> struct equal_to<void> {
313  using is_transparent = void;
314 
315  template <class T, class U>
316  constexpr auto operator () (T&& t, U&& u) const -> decltype(
317  core::forward<T>(t) == core::forward<U>(u)
318  ) { return core::forward<T>(t) == core::forward<U>(u); }
319 };
320 
321 template <> struct not_equal_to<void> {
322  using is_transparent = void;
323 
324  template <class T, class U>
325  constexpr auto operator () (T&& t, U&& u) const -> decltype(
326  core::forward<T>(t) != core::forward<U>(u)
327  ) { return core::forward<T>(t) != core::forward<U>(u); }
328 };
329 
330 template <> struct greater_equal<void> {
331  using is_transparent = void;
332 
333  template <class T, class U>
334  constexpr auto operator () (T&& t, U&& u) const -> decltype(
335  core::forward<T>(t) >= core::forward<U>(u)
336  ) { return core::forward<T>(t) >= core::forward<U>(u); }
337 };
338 
339 template <> struct less_equal<void> {
340  using is_transparent = void;
341 
342  template <class T, class U>
343  constexpr auto operator () (T&& t, U&& u) const -> decltype(
344  core::forward<T>(t) <= core::forward<U>(u)
345  ) { return core::forward<T>(t) <= core::forward<U>(u); }
346 };
347 
348 template <> struct greater<void> {
349  using is_transparent = void;
350 
351  template <class T, class U>
352  constexpr auto operator () (T&& t, U&& u) const -> decltype(
353  core::forward<T>(t) > core::forward<U>(u)
354  ) { return core::forward<T>(t) > core::forward<U>(u); }
355 };
356 
357 template <> struct less<void> {
358  using is_transparent = void;
359 
360  template <class T, class U>
361  constexpr auto operator () (T&& t, U&& u) const -> decltype(
362  core::forward<T>(t) < core::forward<U>(u)
363  ) { return core::forward<T>(t) < core::forward<U>(u); }
364 };
365 
366 /* function objects -- logical specializations */
367 template <> struct logical_and<void> {
368  using is_transparent = void;
369 
370  template <class T, class U>
371  constexpr auto operator () (T&& t, U&& u) const -> decltype(
372  core::forward<T>(t) and core::forward<U>(u)
373  ) { return core::forward<T>(t) and core::forward<U>(u); }
374 };
375 
376 template <> struct logical_or<void> {
377  using is_transparent = void;
378 
379  template <class T, class U>
380  constexpr auto operator () (T&& t, U&& u) const -> decltype(
381  core::forward<T>(t) or core::forward<U>(u)
382  ) { return core::forward<T>(t) or core::forward<U>(u); }
383 };
384 
385 template <> struct logical_not<void> {
386  using is_transparent = void;
387 
388  template <class T>
389  constexpr auto operator () (T&& t) const -> decltype(
390  not core::forward<T>(t)
391  ) { return not core::forward<T>(t); }
392 };
393 
394 /* function objects -- bitwise specializations */
395 template <> struct bit_and<void> {
396  using is_transparent = void;
397 
398  template <class T, class U>
399  constexpr auto operator () (T&& t, U&& u) const -> decltype(
400  core::forward<T>(t) & core::forward<U>(u)
401  ) { return core::forward<T>(t) & core::forward<U>(u); }
402 };
403 
404 template <> struct bit_or<void> {
405  using is_transparent = void;
406 
407  template <class T, class U>
408  constexpr auto operator () (T&& t, U&& u) const -> decltype(
409  core::forward<T>(t) | core::forward<U>(u)
410  ) { return core::forward<T>(t) | core::forward<U>(u); }
411 };
412 
413 template <> struct bit_xor<void> {
414  using is_transparent = void;
415 
416  template <class T, class U>
417  constexpr auto operator () (T&& t, U&& u) const -> decltype(
418  core::forward<T>(t) ^ core::forward<U>(u)
419  ) { return core::forward<T>(t) ^ core::forward<U>(u); }
420 };
421 
422 template <> struct bit_not<void> {
423  using is_transparent = void;
424 
425  template <class T>
426  constexpr auto operator () (T&& t) const -> decltype(~core::forward<T>(t)) {
427  return ~core::forward<T>(t);
428  }
429 };
430 
431 /* N3980 Implementation */
432 
433 }} /* namespace core::v2 */
434 
435 #endif /* CORE_FUNCTIONAL_HPP */
constexpr auto size(Container const &container) noexcept -> decltype(container.size())
Definition: iterator.hpp:29
auto apply(F &&f, T &&t, index_sequence< I... >) -> decltype(invoke(core::forward< F >(f), ::std::get< I >(core::forward< T >(t))...))
Definition: functional.hpp:92
typename functor_type::return_type return_type
Definition: functional.hpp:71
meta::get< typelist, N > argument
Definition: functional.hpp:66
Copyright © 2013 - 2015 MNMLSTC.
Definition: algorithm.hpp:23
constexpr T && forward(remove_reference_t< T > &t) noexcept
Definition: utility.hpp:27
auto invoke(Functor &&f, Args &&... args) -> enable_if_t< ::std::is_member_pointer< decay_t< Functor >>::value, result_of_t< Functor &&(Args &&...)> >
Definition: functional.hpp:80
typename impl::get< T, N >::type get
Definition: meta.hpp:222
not_fn_functor< decay_t< F > > not_fn(F &&f)
Definition: functional.hpp:143
auto apply(Functor &&f, T &&t) -> decltype(apply(core::forward< Functor >(f), core::forward< T >(t), I
Definition: functional.hpp:100
typename result_of< T >::type result_of_t
auto make_apply(F &&f) -> apply_functor< F >
Definition: functional.hpp:118
typename functor_type::template argument< N > argument
Definition: functional.hpp:75
meta::is_specialization_of< remove_cv_t< T >, ::std::reference_wrapper > is_reference_wrapper
Definition: functional.hpp:30
typename ::std::add_pointer< T >::type add_pointer_t
make_integer_sequence<::std::size_t, N > make_index_sequence
Definition: utility.hpp:52
typename ::std::enable_if< B, T >::type enable_if_t
add_pointer_t< return_type(Args...)> pointer
Definition: functional.hpp:63
static constexpr auto arity
Definition: functional.hpp:73