All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
functors.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
16 #ifndef PAAL_FUNCTORS_HPP
17 #define PAAL_FUNCTORS_HPP
18 
19 #define BOOST_RESULT_OF_USE_DECLTYPE
20 
22 
23 #include <boost/range/adaptor/transformed.hpp>
24 #include <boost/range/iterator_range.hpp>
25 
26 #include <algorithm>
27 #include <cassert>
28 #include <cstddef>
29 #include <tuple>
30 #include <utility>
31 
32 namespace paal {
33 namespace utils {
34 
35 // TODO this will not be needed once C++14 auto lambda parameters become available.
39 struct ignore_param {
45  template <class... Args>
46  ignore_param(Args&&...) {}
47 };
48 
52 struct skip_functor {
59  template <typename... Args> void operator()(Args &&... args) const {}
60 };
61 
69 template <typename T, T t> struct return_constant_functor {
78  template <typename... Args> T operator()(Args &&... args) const {
79  return t;
80  }
81 };
82 
88 template <typename T> struct dynamic_return_constant_functor {
95 
104  template <typename... Args> T operator()(Args &&... args) const {
105  return m_t;
106  }
107 
108  private:
109  T m_t;
110 };
111 
120 template <typename T>
123 }
124 
137  template <typename Arg> auto operator()(Arg &&arg) const->Arg {
138  return std::forward<Arg>(arg);
139  }
140 };
141 
152 template <typename F, typename G>
153 auto compose(F f, G g) {
154  return std::bind(f, std::bind(g, std::placeholders::_1));
155 }
156 
167 template <typename F, typename... Fs>
168 auto compose(F f, Fs... fs) {
169  return compose(f, compose(fs...));
170 }
171 
172 namespace detail {
174  template <typename T> void get(T t) {}
175 }
176 
177 // TODO make it work also with std::tuple, for that use ADL trick for get
178 // function and branch compile time between boost::tuples::length and
179 // std::tuple_size.
185 template <class F>
187  F m_f;
188  public:
194  tuple_uncurry(F f) : m_f(f) {}
195 
202  template <class Tuple>
203  auto operator()(Tuple&& t) const {
204  using detail::get;
205  return m_f(get<0>(t), get<1>(t));
206  }
207 };
208 
217 template <class F> auto make_tuple_uncurry(F f) { return tuple_uncurry<F>(f); }
218 
222 struct always_false : public return_constant_functor<bool, false> {};
223 
227 struct always_true : public return_constant_functor<bool, true> {};
228 
232 struct return_zero_functor : public return_constant_functor<int, 0> {};
233 
237 struct return_one_functor : public return_constant_functor<int, 1> {};
238 
249  template <typename... Args> void operator()(Args &&... args) const {
250  assert(false);
251  }
252 };
253 
266  template <typename T> T operator()(const T &t) const { return t; }
267 };
268 
275 template <typename Functor, typename CounterType = int>
277  public:
284  counting_functor_adaptor(Functor f, CounterType &cnt)
285  : m_cnt(&cnt), m_functor(std::move(f)) {}
286 
294  template <typename... Args>
295  auto operator()(Args &&... args)
296  ->decltype(std::declval<Functor>()(std::forward<Args>(args)...)) {
297  ++(*m_cnt);
298  return m_functor(std::forward<Args>(args)...);
299  }
300 
301  private:
302  CounterType *m_cnt;
303  Functor m_functor;
304 };
305 
316 template <typename CounterType = int, typename Functor>
317 auto make_counting_functor_adaptor(Functor f, CounterType &cnt) {
318  return counting_functor_adaptor<Functor, CounterType>(std::move(f), cnt);
319 }
320 
326 template <typename Array> class array_to_functor {
327  public:
334  array_to_functor(const Array &array, int offset = 0)
335  : m_array(array), m_offset(offset) {}
336 
338  typedef decltype(std::declval<const Array>()[0]) Value;
339 
347  Value operator()(int a) const { return m_array.get()[a + m_offset]; }
348 
349  private:
350  std::reference_wrapper<const Array> m_array;
351  int m_offset;
352 };
353 
363 template <typename Array>
364 auto make_array_to_functor(const Array &a, int offset = 0) {
365  return array_to_functor<Array>(a, offset);
366 }
367 
377 template <typename Functor> struct assignable_functor {
383  assignable_functor(Functor const &f) : m_f(f) {}
384  assignable_functor() = default;
385 
393  assignable_functor &operator=(Functor &f) { m_f = f; }
394 
402  template <typename... Args>
403  auto operator()(Args &&... args) const->decltype(
404  std::declval<Functor>()(std::forward<Args>(args)...)) {
405  return m_f.get()(std::forward<Args>(args)...);
406  }
407 
408  private:
409  std::reference_wrapper<const Functor> m_f;
410 };
411 
420 template <typename Functor>
421 auto make_assignable_functor(Functor &f) {
422  return assignable_functor<Functor>(f);
423 }
424 
432 template <typename Functor> struct lift_iterator_functor {
438  lift_iterator_functor(Functor f) : m_f(std::move(f)) {}
439 
448  template <typename Iterator>
449  auto operator()(Iterator iter) const->decltype(
450  std::declval<Functor>()(*iter)) {
451  return m_f(*iter);
452  }
453 
454  private:
455  Functor m_f;
456 };
457 
466 template <typename Functor>
467 auto make_lift_iterator_functor(Functor f) {
469 }
470 
471 //************ The set of comparison functors *******************
472 // functors are equivalent to corresponding std functors (e.g. std::less) but
473 // are not templated
474 
478 struct greater {
488  template <class T>
489  auto operator()(const T &x, const T &y) const->decltype(x > y) {
490  return x > y;
491  }
492 };
493 
497 struct less {
507  template <class T>
508  auto operator()(const T &x, const T &y) const->decltype(x < y) {
509  return x < y;
510  }
511 };
512 
527  template <class T1, class T2>
528  auto operator()(const T1 &x, const T2 &y) const->decltype(x >= y) {
529  return x >= y;
530  }
531 };
532 
536 struct less_equal {
547  template <class T1, class T2>
548  auto operator()(const T1 &x, const T2 &y) const->decltype(x <= y) {
549  return x <= y;
550  }
551 };
552 
556 struct equal_to {
566  template <class T>
567  auto operator()(const T &x, const T &y) const->decltype(x == y) {
568  return x == y;
569  }
570 };
571 
584  template <class T, class U>
585  auto operator()(T &&t, U &&u) const->decltype(t == u) {
586  return t == u;
587  }
588 };
589 
593 struct not_equal_to {
603  template <class T>
604  auto operator()(const T &x, const T &y) const->decltype(x != y) {
605  return x != y;
606  }
607 };
608 
612 template <typename Functor, typename Compare = less>
620  functor_to_comparator(Functor f, Compare c = Compare()) : m_f(f), m_c(c) {}
621 
631  template <typename T>
632  auto operator()(const T &left, const T &right) const->decltype(
633  std::declval<Compare>()(std::declval<Functor>()(left),
634  std::declval<Functor>()(right))) {
635  return m_c(m_f(left), m_f(right));
636  }
637 
638  private:
639  Functor m_f;
640  Compare m_c;
641 };
642 
653 template <typename Functor, typename Compare = less>
654 auto make_functor_to_comparator(Functor functor, Compare compare = Compare()) {
655  return functor_to_comparator<Functor, Compare>(std::move(functor),
656  std::move(compare));
657 }
658 
660 template <typename Functor, typename ScaleType,
661  typename ReturnType = ScaleType>
663 
670  scale_functor(Functor f, ScaleType s) : m_f(std::move(f)), m_s(s) {}
671 
680  template <typename Arg> ReturnType operator()(Arg &&arg) const {
681  return m_s * m_f(std::forward<Arg>(arg));
682  }
683 
684  private:
685  Functor m_f;
686  ScaleType m_s;
687 };
688 
700 template <typename ScaleType, typename ReturnType = ScaleType,
701  typename Functor>
702 auto make_scale_functor(Functor f, ScaleType s) {
704 }
705 
706 //****************************** This is a set of functors representing standard
707 // arithmetic
708 // operations that is +, -, etc. These are equivalent to standard std:: structs
709 // but are not templated
711 struct plus {
720  template <typename T1, typename T2>
721  auto operator()(T1&& left, T2&& right) const
722  -> decltype(std::forward<T1>(left) + std::forward<T2>(right)) {
723  return std::forward<T1>(left) + std::forward<T2>(right);
724  }
725  // TODO change other operations (minus, max, less, etc..) like this one:
726  // with two different types and perfect forwarding
727 };
728 
730 struct minus {
738  template <typename T>
739  auto operator()(const T &left,
740  const T &right) const->decltype(left - right) {
741  return left - right;
742  }
743 };
744 
746 struct max {
754  template <typename T>
755  auto operator()(const T &left,
756  const T &right) const->decltype(std::max(left, right)) {
757  return std::max(left, right);
758  }
759 };
760 
762 struct min {
770  template <typename T>
771  auto operator()(const T &left,
772  const T &right) const->decltype(std::min(left, right)) {
773  return std::min(left, right);
774  }
775 };
776 
777 //****************************** This is a set of functors representing standard
778 // boolean operations
779 // that is !, &&, ||. These are equivalent to standard std:: structs but are not
780 // templated
781 //(only operator() is templated)
782 
784 struct Not {
792  template <typename T> auto operator()(const T &b) const->decltype(!b) {
793  return !b;
794  }
795 };
796 
798 struct Or {
808  template <typename T>
809  auto operator()(const T &left,
810  const T &right) const->decltype(left || right) {
811  return left || right;
812  }
813 };
814 
816 struct And {
826  template <typename T>
827  auto operator()(const T &left,
828  const T &right) const->decltype(left &&right) {
829  return left && right;
830  }
831 };
832 
835 template <typename FunctorLeft, typename FunctorRight, typename Operator>
844  lift_binary_operator_functor(FunctorLeft left = FunctorLeft(),
845  FunctorRight right = FunctorRight(),
846  Operator op = Operator())
847  : m_left(std::move(left)), m_right(std::move(right)),
848  m_operator(std::move(op)) {}
849 
857  template <typename... Args>
858  auto operator()(Args &&... args) const->decltype(std::declval<Operator>()(
859  std::declval<FunctorLeft>()(std::forward<Args>(args)...),
860  std::declval<FunctorRight>()(std::forward<Args>(args)...))) {
861  return m_operator(m_left(std::forward<Args>(args)...),
862  m_right(std::forward<Args>(args)...));
863  }
864 
865  private:
866  FunctorLeft m_left;
867  FunctorRight m_right;
868  Operator m_operator;
869 };
870 
883 template <typename FunctorLeft, typename FunctorRight, typename Operator>
884 auto make_lift_binary_operator_functor(FunctorLeft left, FunctorRight right,
885  Operator op) {
887  std::move(left), std::move(right), std::move(op));
888 }
889 
890 //******************** this is set of functors
891 // allowing to compose functors using
892 // standard logical operators
893 
895 template <typename Functor> struct not_functor {
901  not_functor(Functor functor = Functor()) : m_functor(functor) {}
902 
910  template <typename... Args>
911  auto operator()(Args &&... args) const->decltype(
912  std::declval<Functor>()(std::forward<Args>(args)...)) {
913  return !m_functor(std::forward<Args>(args)...);
914  }
915 
916  private:
917  Functor m_functor;
918 };
919 
921 template <typename Functor>
922 auto make_not_functor(Functor functor) {
923  return not_functor<Functor>(std::move(functor));
924 }
925 
927 template <typename FunctorLeft, typename FunctorRight>
929  : public lift_binary_operator_functor<FunctorLeft, FunctorRight, Or> {
931 
938  or_functor(FunctorLeft left = FunctorLeft(),
939  FunctorRight right = FunctorRight())
940  : base(std::move(left), std::move(right)) {}
941 };
942 
944 template <typename FunctorLeft, typename FunctorRight>
945 auto make_or_functor(FunctorLeft left,
946  FunctorRight right) {
947  return or_functor<FunctorLeft, FunctorRight>(std::move(left),
948  std::move(right));
949 }
950 
952 template <typename FunctorLeft, typename FunctorRight>
954  : public lift_binary_operator_functor<FunctorLeft, FunctorRight, And> {
956 
963  and_functor(FunctorLeft left = FunctorLeft(),
964  FunctorRight right = FunctorRight())
965  : base(std::move(left), std::move(right)) {}
966 };
967 
969 template <typename FunctorLeft, typename FunctorRight>
970 auto make_and_functor(FunctorLeft left, FunctorRight right) {
971  return and_functor<FunctorLeft, FunctorRight>(std::move(left),
972  std::move(right));
973 }
974 
976 template <typename FunctorLeft, typename FunctorRight>
978  FunctorLeft, FunctorRight, not_equal_to> {
979  typedef lift_binary_operator_functor<FunctorLeft, FunctorRight,
981 
988  xor_functor(FunctorLeft left = FunctorLeft(),
989  FunctorRight right = FunctorRight())
990  : base(std::move(left), std::move(right)) {}
991 };
992 
994 template <typename FunctorLeft, typename FunctorRight>
995 auto make_xor_functor(FunctorLeft left, FunctorRight right) {
996  return xor_functor<FunctorLeft, FunctorRight>(std::move(left),
997  std::move(right));
998 }
999 
1001 template <std::size_t I>
1002 struct tuple_get {
1009  template <typename Tuple>
1010  //TODO change to decltype(auto), when it starts working
1011  auto operator()(Tuple &&tuple) const ->
1012  decltype(std::get<I>(std::forward<Tuple>(tuple))) {
1013  return std::get<I>(std::forward<Tuple>(tuple));
1014  }
1015 };
1016 
1017 }
1018 }
1019 #endif // PAAL_FUNCTORS_HPP
lift_iterator_functor(Functor f)
constructor
Definition: functors.hpp:438
auto make_or_functor(FunctorLeft left, FunctorRight right)
make for or_functor
Definition: functors.hpp:945
greater_equal functor
Definition: functors.hpp:516
Functor returns always the same number (dynamic version).
Definition: functors.hpp:88
equal_to functor
Definition: functors.hpp:556
less functor
Definition: functors.hpp:497
auto operator()(const T &b) const -> decltype(!b)
operator()
Definition: functors.hpp:792
auto operator()(const T &x, const T &y) const -> decltype(x > y)
operator()
Definition: functors.hpp:489
auto operator()(Args &&...args) -> decltype(std::declval< Functor >()(std::forward< Args >(args)...))
increments the counter and checks if the given limit is reached.
Definition: functors.hpp:295
functor return false
Definition: functors.hpp:222
tuple_uncurry(F f)
constructor
Definition: functors.hpp:194
void operator()(Args &&...args) const
operator
Definition: functors.hpp:59
Type that can be constructed from anything and has no other functionality.
Definition: functors.hpp:39
counting_functor_adaptor(Functor f, CounterType &cnt)
Constructor.
Definition: functors.hpp:284
removes reference
Definition: functors.hpp:257
auto make_tuple_uncurry(F f)
make for tuple_uncurry
Definition: functors.hpp:217
auto operator()(const T &left, const T &right) const -> decltype(std::min(left, right))
operator()
Definition: functors.hpp:771
and_functor(FunctorLeft left=FunctorLeft(), FunctorRight right=FunctorRight())
constructor
Definition: functors.hpp:963
auto make_dynamic_return_constant_functor(T t)
make function for dynamic_return_constant_functor
Definition: functors.hpp:121
auto operator()(const T1 &x, const T2 &y) const -> decltype(x<=y)
operator()
Definition: functors.hpp:548
Functor returns always the same number. The number has to be known at compile time.
Definition: functors.hpp:69
auto operator()(const T1 &x, const T2 &y) const -> decltype(x >=y)
operator()
Definition: functors.hpp:528
Adapts array as function, providing operator()().
Definition: functors.hpp:326
lift_binary_operator_functor(FunctorLeft left=FunctorLeft(), FunctorRight right=FunctorRight(), Operator op=Operator())
constructor
Definition: functors.hpp:844
auto make_xor_functor(FunctorLeft left, FunctorRight right)
make for Xor
Definition: functors.hpp:995
For given functor f, lift_iterator_functor provides operator()(Iterator iterator) which returns f(*it...
Definition: functors.hpp:432
not_equal_to functor
Definition: functors.hpp:593
array_to_functor(const Array &array, int offset=0)
constructor
Definition: functors.hpp:334
T operator()(Args &&...args) const
operator
Definition: functors.hpp:78
auto make_functor_to_comparator(Functor functor, Compare compare=Compare())
make for functor to comparator
Definition: functors.hpp:654
void operator()(Args &&...args) const
operator()
Definition: functors.hpp:249
auto compose(F f, G g)
functor composition: x -&gt; f(g(x))
Definition: functors.hpp:153
auto operator()(const T &x, const T &y) const -> decltype(x!=y)
operator
Definition: functors.hpp:604
auto operator()(Iterator iter) const -> decltype(std::declval< Functor >()(*iter))
operator()
Definition: functors.hpp:449
auto operator()(const T &left, const T &right) const -> decltype(std::declval< Compare >()(std::declval< Functor >()(left), std::declval< Functor >()(right)))
operator()
Definition: functors.hpp:632
auto make_assignable_functor(Functor &f)
make function for assignable_functor
Definition: functors.hpp:421
xor_functor(FunctorLeft left=FunctorLeft(), FunctorRight right=FunctorRight())
constructor
Definition: functors.hpp:988
auto make_not_functor(Functor functor)
make for Not
Definition: functors.hpp:922
Functor does nothing.
Definition: functors.hpp:52
ReturnType operator()(Arg &&arg) const
operator()
Definition: functors.hpp:680
auto operator()(const T &left, const T &right) const -> decltype(left||right)
operator
Definition: functors.hpp:809
auto operator()(Arg &&arg) const -> Arg
operator()
Definition: functors.hpp:137
scale_functor(Functor f, ScaleType s)
constructor
Definition: functors.hpp:670
auto operator()(Args &&...args) const -> decltype(std::declval< Functor >()(std::forward< Args >(args)...))
operator()
Definition: functors.hpp:911
auto make_array_to_functor(const Array &a, int offset=0)
make function for array_to_functor
Definition: functors.hpp:364
auto make_lift_binary_operator_functor(FunctorLeft left, FunctorRight right, Operator op)
make function for lift_binary_operator_functor
Definition: functors.hpp:884
Class for comparing floating point.
Definition: floating.hpp:26
less_equal functor
Definition: functors.hpp:536
greater functor
Definition: functors.hpp:478
auto operator()(const T &left, const T &right) const -> decltype(left &&right)
operator()
Definition: functors.hpp:827
Functor that scales another functor.
Definition: functors.hpp:662
auto operator()(Tuple &&t) const
operator
Definition: functors.hpp:203
auto make_lift_iterator_functor(Functor f)
make function for lift_iterator_functor
Definition: functors.hpp:467
functor_to_comparator(Functor f, Compare c=Compare())
constructor
Definition: functors.hpp:620
auto operator()(T &&t, U &&u) const -> decltype(t==u)
operator()
Definition: functors.hpp:585
auto make_counting_functor_adaptor(Functor f, CounterType &cnt)
make function for counting_functor_adaptor
Definition: functors.hpp:317
functors calls assert(false).
Definition: functors.hpp:242
functor for std::tuple::get&lt;I&gt;
Definition: functors.hpp:1002
functor returns its argument
Definition: functors.hpp:128
transforms a functor taking multiple parameters into a functor taking a tuple parameter.
Definition: functors.hpp:186
TODO equivalent to c++14 equal_to&lt;&gt;, remove when appears.
Definition: functors.hpp:573
not_functor(Functor functor=Functor())
constructor
Definition: functors.hpp:901
auto operator()(const T &x, const T &y) const -> decltype(x==y)
operator()
Definition: functors.hpp:567
T operator()(const T &t) const
operator()
Definition: functors.hpp:266
auto operator()(Tuple &&tuple) const -> decltype(std::get< I >(std::forward< Tuple >(tuple)))
operator()
Definition: functors.hpp:1011
auto operator()(T1 &&left, T2 &&right) const -> decltype(std::forward< T1 >(left)+std::forward< T2 >(right))
operator()
Definition: functors.hpp:721
assignable_functor & operator=(Functor &f)
assign operator
Definition: functors.hpp:393
ignore_param(Args &&...)
constructor
Definition: functors.hpp:46
auto make_scale_functor(Functor f, ScaleType s)
make for scale_functor
Definition: functors.hpp:702
auto operator()(Args &&...args) const -> decltype(std::declval< Functor >()(std::forward< Args >(args)...))
operator()
Definition: functors.hpp:403
auto operator()(Args &&...args) const -> decltype(std::declval< Operator >()(std::declval< FunctorLeft >()(std::forward< Args >(args)...), std::declval< FunctorRight >()(std::forward< Args >(args)...)))
operator
Definition: functors.hpp:858
T operator()(Args &&...args) const
operator
Definition: functors.hpp:104
auto make_and_functor(FunctorLeft left, FunctorRight right)
make and_functor
Definition: functors.hpp:970
auto operator()(const T &left, const T &right) const -> decltype(std::max(left, right))
operator()
Definition: functors.hpp:755
or_functor(FunctorLeft left=FunctorLeft(), FunctorRight right=FunctorRight())
constructor
Definition: functors.hpp:938
auto operator()(const T &left, const T &right) const -> decltype(left-right)
operator()
Definition: functors.hpp:739
assignable_functor(Functor const &f)
constructor
Definition: functors.hpp:383
Counts number of calls.
Definition: functors.hpp:276
auto operator()(const T &x, const T &y) const -> decltype(x< y)
operator()
Definition: functors.hpp:508
functor return true
Definition: functors.hpp:227
Wrapper around a functor which adds assigmnent operator as well as default constructor. Note, this struct might be dangerous. Using this struct correctly requires the underlying functor to live at least as long as this wrapper.
Definition: functors.hpp:377