Backport
functional.hpp
Go to the documentation of this file.
1 
7 /*
8  The MIT License (MIT)
9 
10  Copyright (c) 2020 Matthew Rodusek All rights reserved.
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy
13  of this software and associated documentation files (the "Software"), to deal
14  in the Software without restriction, including without limitation the rights
15  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  copies of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in
20  all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  SOFTWARE.
29 */
30 #ifndef BPSTD_FUNCTIONAL_HPP
31 #define BPSTD_FUNCTIONAL_HPP
32 
33 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
34 # pragma once
35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
36 
37 #include "detail/config.hpp"
38 #include "type_traits.hpp"
39 #include "utility.hpp"
40 #include "detail/invoke.hpp"
41 
42 #include <functional> // to proxy API
43 
44 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
45 
46 namespace bpstd {
47 
54  template <typename Func, typename... Args>
55  constexpr invoke_result_t<Func,Args...> invoke(Func&& function, Args&&... args)
56  noexcept(is_nothrow_invocable<Func,Args...>::value);
57 
58  namespace detail {
59  template <typename Fn>
60  struct not_fn_t
61  {
62  Fn fn;
63 
64  template <typename...Args>
65  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
66  auto operator()(Args&&... args) &
67  noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...)))
68  -> decltype(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...))
69  {
70  return !::bpstd::invoke(fn, bpstd::forward<Args>(args)...);
71  }
72 
73  template <typename...Args>
74  inline BPSTD_INLINE_VISIBILITY BPSTD_CPP14_CONSTEXPR
75  auto operator()(Args&&... args) &&
76  noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...)))
77  -> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...))
78  {
79  return !::bpstd::invoke(std::move(fn), bpstd::forward<Args>(args)...);
80  }
81 
82  template <typename...Args>
83  inline BPSTD_INLINE_VISIBILITY constexpr
84  auto operator()(Args&&... args) const&
85  noexcept(noexcept(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...)))
86  -> decltype(!::bpstd::invoke(fn, ::bpstd::forward<Args>(args)...))
87  {
88  return !::bpstd::invoke(fn, bpstd::forward<Args>(args)...);
89  }
90 
91  template <typename...Args>
92  inline BPSTD_INLINE_VISIBILITY constexpr
93  auto operator()(Args&&... args) const&&
94  noexcept(noexcept(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...)))
95  -> decltype(!::bpstd::invoke(std::move(fn), ::bpstd::forward<Args>(args)...))
96  {
97  return !::bpstd::invoke(std::move(fn), bpstd::forward<Args>(args)...);
98  }
99  };
100  } // namespace detail
101 
108  template <typename Fn>
109  constexpr detail::not_fn_t<decay_t<Fn>> not_fn(Fn&& fn);
110 
111  //============================================================================
112  // struct : plus
113  //============================================================================
114 
115  template <typename T = void>
116  struct plus
117  {
118  inline BPSTD_INLINE_VISIBILITY constexpr
119  T operator()(const T& lhs, const T& rhs)
120  const
121  {
122  return lhs + rhs;
123  }
124  };
125 
126  template <>
127  struct plus<void>
128  {
129  using is_transparent = true_type;
130 
131  template <typename T, typename U>
132  inline BPSTD_INLINE_VISIBILITY constexpr
133  auto operator()(T&& lhs, U&& rhs) const
134  -> decltype(::bpstd::forward<T>(lhs) + ::bpstd::forward<U>(rhs))
135  {
136  return bpstd::forward<T>(lhs) + bpstd::forward<U>(rhs);
137  }
138  };
139 
140  //============================================================================
141  // struct : minus
142  //============================================================================
143 
144  template <typename T = void>
145  struct minus
146  {
147  inline BPSTD_INLINE_VISIBILITY constexpr
148  T operator()(const T& lhs, const T& rhs)
149  const
150  {
151  return lhs - rhs;
152  }
153  };
154 
155  template <>
156  struct minus<void>
157  {
158  using is_transparent = true_type;
159 
160  template <typename T, typename U>
161  inline BPSTD_INLINE_VISIBILITY constexpr
162  auto operator()(T&& lhs, U&& rhs) const
163  -> decltype(::bpstd::forward<T>(lhs) - ::bpstd::forward<U>(rhs))
164  {
165  return bpstd::forward<T>(lhs) - bpstd::forward<U>(rhs);
166  }
167  };
168 
169  //============================================================================
170  // struct : multiplies
171  //============================================================================
172 
173  template <typename T = void>
174  struct multiplies
175  {
176  inline BPSTD_INLINE_VISIBILITY constexpr
177  T operator()(const T& lhs, const T& rhs)
178  const
179  {
180  return lhs * rhs;
181  }
182  };
183 
184  template <>
185  struct multiplies<void>
186  {
187  using is_transparent = true_type;
188 
189  template <typename T, typename U>
190  inline BPSTD_INLINE_VISIBILITY constexpr
191  auto operator()(T&& lhs, U&& rhs) const
192  -> decltype(::bpstd::forward<T>(lhs) * ::bpstd::forward<U>(rhs))
193  {
194  return bpstd::forward<T>(lhs) * bpstd::forward<U>(rhs);
195  }
196  };
197 
198  //============================================================================
199  // struct : divides
200  //============================================================================
201 
202  template <typename T = void>
203  struct divides
204  {
205  inline BPSTD_INLINE_VISIBILITY constexpr
206  T operator()(const T& lhs, const T& rhs)
207  const
208  {
209  return lhs / rhs;
210  }
211  };
212 
213  template <>
214  struct divides<void>
215  {
216  using is_transparent = true_type;
217 
218  template <typename T, typename U>
219  inline BPSTD_INLINE_VISIBILITY constexpr
220  auto operator()(T&& lhs, U&& rhs) const
221  -> decltype(::bpstd::forward<T>(lhs) / ::bpstd::forward<U>(rhs))
222  {
223  return bpstd::forward<T>(lhs) / bpstd::forward<U>(rhs);
224  }
225  };
226 
227  //============================================================================
228  // struct : modulus
229  //============================================================================
230 
231  template <typename T = void>
232  struct modulus
233  {
234  inline BPSTD_INLINE_VISIBILITY constexpr
235  T operator()(const T& lhs, const T& rhs)
236  const
237  {
238  return lhs % rhs;
239  }
240  };
241 
242  template <>
243  struct modulus<void>
244  {
245  using is_transparent = true_type;
246 
247  template <typename T, typename U>
248  inline BPSTD_INLINE_VISIBILITY constexpr
249  auto operator()(T&& lhs, U&& rhs) const
250  -> decltype(::bpstd::forward<T>(lhs) % ::bpstd::forward<U>(rhs))
251  {
252  return bpstd::forward<T>(lhs) % bpstd::forward<U>(rhs);
253  }
254  };
255 
256  //============================================================================
257  // struct : negate
258  //============================================================================
259 
260  template <typename T = void>
261  struct negate
262  {
263  inline BPSTD_INLINE_VISIBILITY constexpr
264  T operator()(const T& arg)
265  const
266  {
267  return -arg;
268  }
269  };
270 
271  template <>
272  struct negate<void>
273  {
274  using is_transparent = true_type;
275 
276  template <typename T>
277  inline BPSTD_INLINE_VISIBILITY constexpr
278  auto operator()(T&& arg) const
279  -> decltype(-::bpstd::forward<T>(arg))
280  {
281  return -bpstd::forward<T>(arg);
282  }
283  };
284 
285  //============================================================================
286  // struct : equal_to
287  //============================================================================
288 
289  template <typename T = void>
290  struct equal_to
291  {
292  inline BPSTD_INLINE_VISIBILITY constexpr
293  bool operator()(const T& lhs, const T& rhs)
294  const
295  {
296  return lhs == rhs;
297  }
298  };
299 
300  template <>
301  struct equal_to<void>
302  {
303  using is_transparent = true_type;
304 
305  template <typename T, typename U>
306  inline BPSTD_INLINE_VISIBILITY constexpr
307  auto operator()(T&& lhs, U&& rhs) const
308  -> decltype(::bpstd::forward<T>(lhs) == ::bpstd::forward<U>(rhs))
309  {
310  return bpstd::forward<T>(lhs) == bpstd::forward<U>(rhs);
311  }
312  };
313 
314  //============================================================================
315  // struct : not_equal_to
316  //============================================================================
317 
318  template <typename T = void>
320  {
321  inline BPSTD_INLINE_VISIBILITY constexpr
322  bool operator()(const T& lhs, const T& rhs)
323  const
324  {
325  return lhs != rhs;
326  }
327  };
328 
329  template <>
330  struct not_equal_to<void>
331  {
332  using is_transparent = true_type;
333 
334  template <typename T, typename U>
335  inline BPSTD_INLINE_VISIBILITY constexpr
336  auto operator()(T&& lhs, U&& rhs) const
337  -> decltype(::bpstd::forward<T>(lhs) != ::bpstd::forward<U>(rhs))
338  {
339  return bpstd::forward<T>(lhs) != bpstd::forward<U>(rhs);
340  }
341  };
342 
343  //============================================================================
344  // struct : greater
345  //============================================================================
346 
347  template <typename T = void>
348  struct greater
349  {
350  inline BPSTD_INLINE_VISIBILITY constexpr
351  bool operator()(const T& lhs, const T& rhs)
352  const
353  {
354  return lhs > rhs;
355  }
356  };
357 
358  template <>
359  struct greater<void>
360  {
361  using is_transparent = true_type;
362 
363  template <typename T, typename U>
364  inline BPSTD_INLINE_VISIBILITY constexpr
365  auto operator()(T&& lhs, U&& rhs) const
366  -> decltype(::bpstd::forward<T>(lhs) > ::bpstd::forward<U>(rhs))
367  {
368  return bpstd::forward<T>(lhs) > bpstd::forward<U>(rhs);
369  }
370  };
371 
372  //============================================================================
373  // struct : greater_equal
374  //============================================================================
375 
376  template <typename T = void>
378  {
379  inline BPSTD_INLINE_VISIBILITY constexpr
380  bool operator()(const T& lhs, const T& rhs)
381  const
382  {
383  return lhs >= rhs;
384  }
385  };
386 
387  template <>
388  struct greater_equal<void>
389  {
390  using is_transparent = true_type;
391 
392  template <typename T, typename U>
393  inline BPSTD_INLINE_VISIBILITY constexpr
394  auto operator()(T&& lhs, U&& rhs) const
395  -> decltype(::bpstd::forward<T>(lhs) >= ::bpstd::forward<U>(rhs))
396  {
397  return bpstd::forward<T>(lhs) >= bpstd::forward<U>(rhs);
398  }
399  };
400 
401  //============================================================================
402  // struct : less
403  //============================================================================
404 
405  template <typename T = void>
406  struct less
407  {
408  inline BPSTD_INLINE_VISIBILITY constexpr
409  bool operator()(const T& lhs, const T& rhs)
410  const
411  {
412  return lhs < rhs;
413  }
414  };
415 
416  template <>
417  struct less<void>
418  {
419  using is_transparent = true_type;
420 
421  template <typename T, typename U>
422  inline BPSTD_INLINE_VISIBILITY constexpr
423  auto operator()(T&& lhs, U&& rhs) const
424  -> decltype(::bpstd::forward<T>(lhs) < ::bpstd::forward<U>(rhs))
425  {
426  return bpstd::forward<T>(lhs) < bpstd::forward<U>(rhs);
427  }
428  };
429 
430  //============================================================================
431  // struct : less_equal
432  //============================================================================
433 
434  template <typename T = void>
435  struct less_equal
436  {
437  inline BPSTD_INLINE_VISIBILITY constexpr
438  bool operator()(const T& lhs, const T& rhs)
439  const
440  {
441  return lhs <= rhs;
442  }
443  };
444 
445  template <>
446  struct less_equal<void>
447  {
448  using is_transparent = true_type;
449 
450  template <typename T, typename U>
451  inline BPSTD_INLINE_VISIBILITY constexpr
452  auto operator()(T&& lhs, U&& rhs) const
453  -> decltype(::bpstd::forward<T>(lhs) <= ::bpstd::forward<U>(rhs))
454  {
455  return bpstd::forward<T>(lhs) <= bpstd::forward<U>(rhs);
456  }
457  };
458 
459  //============================================================================
460  // struct : logical_and
461  //============================================================================
462 
463  template <typename T = void>
464  struct logical_and
465  {
466  inline BPSTD_INLINE_VISIBILITY constexpr
467  bool operator()(const T& lhs, const T& rhs)
468  const
469  {
470  return lhs && rhs;
471  }
472  };
473 
474  template <>
475  struct logical_and<void>
476  {
477  using is_transparent = true_type;
478 
479  template <typename T, typename U>
480  inline BPSTD_INLINE_VISIBILITY constexpr
481  auto operator()(T&& lhs, U&& rhs) const
482  -> decltype(::bpstd::forward<T>(lhs) && ::bpstd::forward<U>(rhs))
483  {
484  return bpstd::forward<T>(lhs) && bpstd::forward<U>(rhs);
485  }
486  };
487 
488  //============================================================================
489  // struct : logical_or
490  //============================================================================
491 
492  template <typename T = void>
493  struct logical_or
494  {
495  inline BPSTD_INLINE_VISIBILITY constexpr
496  bool operator()(const T& lhs, const T& rhs)
497  const
498  {
499  return lhs || rhs;
500  }
501  };
502 
503  template <>
504  struct logical_or<void>
505  {
506  using is_transparent = true_type;
507 
508  template <typename T, typename U>
509  inline BPSTD_INLINE_VISIBILITY constexpr
510  auto operator()(T&& lhs, U&& rhs) const
511  -> decltype(::bpstd::forward<T>(lhs) || ::bpstd::forward<U>(rhs))
512  {
513  return bpstd::forward<T>(lhs) || bpstd::forward<U>(rhs);
514  }
515  };
516 
517  //============================================================================
518  // struct : logical_not
519  //============================================================================
520 
521  template <typename T = void>
522  struct logical_not
523  {
524  inline BPSTD_INLINE_VISIBILITY constexpr
525  bool operator()(const T& arg)
526  const
527  {
528  return !arg;
529  }
530  };
531 
532  template <>
533  struct logical_not<void>
534  {
535  using is_transparent = true_type;
536 
537  template <typename T>
538  inline BPSTD_INLINE_VISIBILITY constexpr
539  auto operator()(T&& arg) const
540  -> decltype(!::bpstd::forward<T>(arg))
541  {
542  return !bpstd::forward<T>(arg);
543  }
544  };
545 
546  //============================================================================
547  // struct : bit_and
548  //============================================================================
549 
550  template <typename T = void>
551  struct bit_and
552  {
553  inline BPSTD_INLINE_VISIBILITY constexpr
554  T operator()(const T& lhs, const T& rhs)
555  const
556  {
557  return lhs & rhs;
558  }
559  };
560 
561  template <>
562  struct bit_and<void>
563  {
564  using is_transparent = true_type;
565 
566  template <typename T, typename U>
567  inline BPSTD_INLINE_VISIBILITY constexpr
568  auto operator()(T&& lhs, U&& rhs) const
569  -> decltype(::bpstd::forward<T>(lhs) & ::bpstd::forward<U>(rhs))
570  {
571  return bpstd::forward<T>(lhs) & bpstd::forward<U>(rhs);
572  }
573  };
574 
575  //============================================================================
576  // struct : bit_or
577  //============================================================================
578 
579  template <typename T = void>
580  struct bit_or
581  {
582  inline BPSTD_INLINE_VISIBILITY constexpr
583  T operator()(const T& lhs, const T& rhs)
584  const
585  {
586  return lhs | rhs;
587  }
588  };
589 
590  template <>
591  struct bit_or<void>
592  {
593  using is_transparent = true_type;
594 
595  template <typename T, typename U>
596  inline BPSTD_INLINE_VISIBILITY constexpr
597  auto operator()(T&& lhs, U&& rhs) const
598  -> decltype(::bpstd::forward<T>(lhs) | ::bpstd::forward<U>(rhs))
599  {
600  return bpstd::forward<T>(lhs) | bpstd::forward<U>(rhs);
601  }
602  };
603 
604  //============================================================================
605  // struct : bit_xor
606  //============================================================================
607 
608  template <typename T = void>
609  struct bit_xor
610  {
611  inline BPSTD_INLINE_VISIBILITY constexpr
612  T operator()(const T& lhs, const T& rhs)
613  const
614  {
615  return lhs ^ rhs;
616  }
617  };
618 
619  template <>
620  struct bit_xor<void>
621  {
622  using is_transparent = true_type;
623 
624  template <typename T, typename U>
625  inline BPSTD_INLINE_VISIBILITY constexpr
626  auto operator()(T&& lhs, U&& rhs) const
627  -> decltype(::bpstd::forward<T>(lhs) ^ ::bpstd::forward<U>(rhs))
628  {
629  return bpstd::forward<T>(lhs) ^ bpstd::forward<U>(rhs);
630  }
631  };
632 
633  //============================================================================
634  // struct : bit_not
635  //============================================================================
636 
637  template <typename T = void>
638  struct bit_not
639  {
640  inline BPSTD_INLINE_VISIBILITY constexpr
641  T operator()(const T& arg)
642  const
643  {
644  return ~arg;
645  }
646  };
647 
648  template <>
649  struct bit_not<void>
650  {
651  using is_transparent = true_type;
652 
653  template <typename T>
654  inline BPSTD_INLINE_VISIBILITY constexpr
655  auto operator()(T&& arg) const
656  -> decltype(~::bpstd::forward<T>(arg))
657  {
658  return ~bpstd::forward<T>(arg);
659  }
660  };
661 
662 } // namespace bpstd
663 
664 //==============================================================================
665 // definition : invoke
666 //==============================================================================
667 
668 template <typename Func, typename... Args>
669 inline BPSTD_INLINE_VISIBILITY constexpr
670 bpstd::invoke_result_t<Func,Args...> bpstd::invoke(Func&& function, Args&&... args)
671  noexcept(is_nothrow_invocable<Func,Args...>::value)
672 {
673  return detail::INVOKE(bpstd::forward<Func>(function), bpstd::forward<Args>(args)...);
674 }
675 
676 
677 //==============================================================================
678 // definition : not_fn
679 //==============================================================================
680 
681 template <typename Fn>
682 inline BPSTD_INLINE_VISIBILITY constexpr
683 bpstd::detail::not_fn_t<bpstd::decay_t<Fn>> bpstd::not_fn(Fn&& fn)
684 {
685  static_assert(
686  is_move_constructible<Fn>::value,
687  "Fn must be move constructible"
688  );
689  static_assert(
690  is_constructible<decay_t<Fn>,Fn>::value,
691  "Fn must be constructible from an instance of fn"
692  );
693 
694  return { bpstd::forward<Fn>(fn) };
695 }
696 
697 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE
698 
699 #endif /* BPSTD_FUNCTIONAL_HPP */
bpstd::equal_to
Definition: functional.hpp:290
bpstd::bit_or
Definition: functional.hpp:580
bpstd::logical_or
Definition: functional.hpp:493
type_traits.hpp
This header provides definitions from the C++ header <type_traits>
bpstd::plus
Definition: functional.hpp:116
bpstd::not_equal_to
Definition: functional.hpp:319
bpstd::invoke
constexpr invoke_result_t< Func, Args... > invoke(Func &&function, Args &&... args) noexcept(is_nothrow_invocable< Func, Args... >::value)
Invoke the Callable object function with the parameters args.
bpstd::not_fn
constexpr detail::not_fn_t< decay_t< Fn > > not_fn(Fn &&fn)
Creates a forwarding call wrapper that returns the negation of the callable object it holds.
bpstd::greater
Definition: functional.hpp:348
bpstd::divides
Definition: functional.hpp:203
bpstd::minus
Definition: functional.hpp:145
bpstd::bit_xor
Definition: functional.hpp:609
bpstd::greater_equal
Definition: functional.hpp:377
bpstd::modulus
Definition: functional.hpp:232
bpstd::bit_and
Definition: functional.hpp:551
bpstd::bit_not
Definition: functional.hpp:638
bpstd::less_equal
Definition: functional.hpp:435
bpstd::less
Definition: functional.hpp:406
bpstd::negate
Definition: functional.hpp:261
bpstd::logical_not
Definition: functional.hpp:522
bpstd::multiplies
Definition: functional.hpp:174
bpstd::logical_and
Definition: functional.hpp:464
utility.hpp
This header provides definitions from the C++ header <utility>