Belle II Software  release-08-01-10
Functional.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 
10 #include <tracking/trackFindingCDC/utilities/FunctorTag.h>
11 
12 #include <type_traits>
13 #include <utility>
14 #include <cassert>
15 #include <cmath>
16 
17 namespace Belle2 {
22  namespace TrackFindingCDC {
23 
25  struct Id {
27  operator FunctorTag();
28 
30  template <class T>
31  T&& operator()(T&& t) const
32  {
33  return std::forward<T>(t);
34  }
35  };
36 
38  template<class T>
39  struct Constant {
41  operator FunctorTag();
42 
43  Constant() = default;
44 
46  explicit Constant(const T& t)
47  : m_t(t)
48  {
49  }
50 
52  template <class S>
53  constexpr const T& operator()(const S&) const
54  {
55  return m_t;
56  }
57 
58  private:
60  T m_t{};
61  };
62 
63 
64 
66  template<class T, class SFINAE = std::enable_if_t<not isFunctor<T>()> >
67  constexpr Constant<T> toFunctor(const T& t)
68  {
69  return Constant<T> {t};
70  }
71 
73  template<class AFunctor, class SFINAE = std::enable_if_t<isFunctor<AFunctor>()> >
74  constexpr const AFunctor & toFunctor(const AFunctor& get)
75  {
76  return get;
77  }
78 
80  template <class T>
81  using ToFunctor = typename std::decay<decltype(toFunctor(std::declval<T>()))>::type;
82 
83 
84 
86  template <class AFunctor1, class AFunctor2>
87  struct Composition {
89  operator FunctorTag();
90 
92  Composition() = default;
93 
95  explicit Composition(const AFunctor2& functor2)
96  : m_functor1()
97  , m_functor2(functor2)
98  {
99  }
100 
102  Composition(const AFunctor1& functor1, const AFunctor2& functor2)
103  : m_functor1(functor1)
104  , m_functor2(functor2)
105  {
106  }
107 
108  private: // Members here for lookup reasons
110  AFunctor1 m_functor1;
111 
113  AFunctor2 m_functor2;
114 
115  public:
117  template<class T>
118  auto operator()(const T& t) const -> decltype(m_functor1(m_functor2(t)))
119  {
120  return m_functor1(m_functor2(t));
121  }
122  };
123 
126  template <class ABinaryOp, class AFunctor1, class AFunctor2 = AFunctor1>
127  struct BinaryJoin : public ABinaryOp {
128  public:
130  operator FunctorTag();
131 
133  BinaryJoin() = default;
134 
136  BinaryJoin(const ABinaryOp& binaryOp, const AFunctor1& functor1, const AFunctor2& functor2)
137  : m_binaryOp(binaryOp)
138  , m_functor1(functor1)
139  , m_functor2(functor2)
140  {
141  }
142 
143 
145  BinaryJoin(const AFunctor1& functor1, const AFunctor2& functor2)
146  : m_binaryOp()
147  , m_functor1(functor1)
148  , m_functor2(functor2)
149  {
150  }
151 
152  private: // Members here for lookup reasons
154  ABinaryOp m_binaryOp;
155 
157  AFunctor1 m_functor1;
158 
160  AFunctor2 m_functor2;
161 
162  public:
164  template <class T1, class T2>
165  auto operator()(const T1& t1, const T2& t2) const -> decltype(m_binaryOp(m_functor1(t1), m_functor2(t2)))
166  {
167  return m_binaryOp(m_functor1(t1), m_functor2(t2));
168  }
169 
171  template <class T>
172  auto operator()(const T& t) const -> decltype(m_binaryOp(m_functor1(t), m_functor2(t)))
173  {
174  return m_binaryOp(m_functor1(t), m_functor2(t));
175  }
176  };
177 
179  template <class AFunctor1, class AFunctor2>
180  struct Alternation {
181 
182  public:
184  operator FunctorTag();
185 
186  private: // Members first for lookup reasons
188  AFunctor1 m_functor1;
189 
191  AFunctor2 m_functor2;
192 
193  public:
195  Alternation() = default;
196 
198  explicit Alternation(const AFunctor1& functor1, const AFunctor2& functor2 = AFunctor2())
199  : m_functor1(functor1)
200  , m_functor2(functor2)
201  {
202  }
203 
204  public:
206  template <class... T>
207  auto impl(int favouredTag __attribute__((unused)), T&& ... t) const
208  -> decltype(m_functor1(std::forward<T>(t)...))
209  {
210  return m_functor1(std::forward<T>(t)...);
211  }
212 
214  template <class... T>
215  auto impl(long disfavouredTag __attribute__((unused)), T&& ... t) const
216  -> decltype(m_functor2(std::forward<T>(t)...))
217  {
218  return m_functor2(std::forward<T>(t)...);
219  }
220 
221  public:
223  template <class... T>
224  auto operator()(T&& ... t) const -> decltype(this->impl(0, std::forward<T>(t)...))
225  {
226  int dispatchTag = 0;
227  return impl(dispatchTag, std::forward<T>(t)...);
228  }
229  };
230 
231 
232  // ******************** (void)(?) ********************
233 
235  struct Void {
237  operator FunctorTag();
238 
240  template <class T>
241  void operator()(T&& t __attribute__((unused))) const
242  {
243  }
244  };
245 
247  template <class AFunctor = Id>
248  using VoidOf = Composition<Void, AFunctor>;
249 
251  template <class AFunctor>
252  using IfApplicable = Alternation<AFunctor, Void>;
253 
255  template<class AFunction, class... T>
256  void invokeIfApplicable(AFunction&& function, T&& ... t)
257  {
258  IfApplicable<AFunction> invokeIfApplicableImpl(std::forward<AFunction>(function));
259  invokeIfApplicableImpl(std::forward<T>(t)...);
260  }
261 
263  template<class ADefault, class AFunctor, class T>
264  ADefault getIfApplicable(AFunctor&& function, T&& obj, ADefault value)
265  {
266  Alternation<AFunctor, Constant<ADefault> > getIfApplicableImpl{std::forward<AFunctor>(function), Constant(value) };
267  return getIfApplicableImpl(std::forward<T>(obj));
268  }
269 
270 
271  // ******************** get<I>(?) ********************
272 
274  template<int I>
275  struct Get {
277  operator FunctorTag();
278 
280  template <class T>
281  auto operator()(const T& t) const -> decltype(std::get<I>(t))
282  {
283  using std::get;
284  return get<I>(t);
285  }
286  };
287 
289  template <int I, class AFunctor = Id>
290  using GetOf = Composition<Get<I>, AFunctor>;
291 
292 
293  // ******************** ?.first ********************
294 
297  using First = Get<0>;
298 
300  template<class AFunctor = Id>
301  using FirstOf = GetOf<0, AFunctor>;
302 
303 
304  // ******************** ?.second ********************
305 
308  using Second = Get<1>;
309 
311  template<class AFunctor = Id>
312  using SecondOf = GetOf<1, AFunctor>;
313 
314 
315  // ******************** ?.size() ********************
316 
318  struct Size {
320  operator FunctorTag();
321 
323  template <class T>
324  auto operator()(const T& t) const -> decltype(t.size())
325  {
326  return t.size();
327  }
328  };
329 
331  template <class AFunctor = Id>
332  using SizeOf = Composition<Size, AFunctor>;
333 
334 
335  // ******************** ?.clear() ********************
336 
338  struct Clear {
340  operator FunctorTag();
341 
343  template <class T>
344  auto operator()(T& t) const -> decltype(t.clear())
345  {
346  return t.clear();
347  }
348  };
349 
351  template <class AFunctor = Id>
352  using ClearOf = Composition<Clear, AFunctor>;
353 
355  using ClearIfApplicable = IfApplicable<Clear>;
356 
358  static const ClearIfApplicable clearIfApplicable{};
359 
360  // ******************** not(?) ********************
361 
363  struct Not {
365  operator FunctorTag();
366 
368  template <class T>
369  auto operator()(const T& t) const -> decltype(not t)
370  {
371  return not t;
372  }
373  };
374 
376  template <class AFunctor = Id>
377  using NotOf = Composition<Not, AFunctor>;
378 
380  template <class AFunctor, class SFINAE = std::enable_if_t<isFunctor<AFunctor>()> >
381  NotOf<AFunctor> operator!(const AFunctor& functor)
382  {
383  return NotOf<AFunctor> {functor};
384  }
385 
386 
387  // ******************** *? ********************
388 
390  struct Deref {
392  operator FunctorTag();
393 
395  template <class T>
396  auto operator()(const T& t) const -> decltype(*t)
397  {
398  return *t;
399  }
400 
402  template <class T>
403  auto operator()(const T* t) const -> decltype(*t)
404  {
405  assert(t != nullptr);
406  return *t;
407  }
408  };
409 
411  template <class AFunctor = Id>
412  using DerefOf = Composition<Deref, AFunctor>;
413 
415  template <class AFunctor = Id>
416  using DerefTo = Composition<AFunctor, Deref>;
417 
418  // ******************** *(?->) ********************
419 
421  struct Indirect {
423  operator FunctorTag();
424 
426  template <class T>
427  auto operator()(const T& t) const -> decltype(*(t.operator->()))
428  {
429  assert(t.operator->() != nullptr);
430  return *(t.operator->());
431  }
432 
434  template <class T>
435  const T& operator()(const T* t) const
436  {
437  assert(t != nullptr);
438  return *t;
439  }
440  };
441 
443  template <class AFunctor = Id>
444  using IndirectOf = Composition<Indirect, AFunctor>;
445 
447  template <class AFunctor = Id>
448  using IndirectTo = Composition<AFunctor, Indirect>;
449 
454  template <class AFunctor>
455  using MayIndirectTo = Alternation<IndirectTo<AFunctor>, AFunctor>;
456  // using MayIndirectTo = AFunctor;
457 
458  // ******************** ? < ? aka less ********************
459 
461  struct Less {
463  operator FunctorTag();
464 
466  template<class T1, class T2>
467  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 < t2)
468  {
469  return t1 < t2;
470  }
471  };
472 
474  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
475  using LessOf = BinaryJoin<Less, AFunctor1, AFunctor2>;
476 
478  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
479  LessOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator<(const ALHS& lhs, const ARHS& rhs)
480  {
481  return {toFunctor(lhs), toFunctor(rhs)};
482  }
483 
484 
485 
486  // ******************** ? > ? aka greater ********************
487 
489  struct Greater {
491  operator FunctorTag();
492 
494  template<class T1, class T2>
495  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 > t2)
496  {
497  return t1 > t2;
498  }
499  };
500 
502  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
503  using GreaterOf = BinaryJoin<Greater, AFunctor1, AFunctor2>;
504 
506  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
507  GreaterOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator>(const ALHS& lhs, const ARHS& rhs)
508  {
509  return {toFunctor(lhs), toFunctor(rhs)};
510  }
511 
512  // ******************** ? == ? aka equal_to ********************
513 
515  struct Equal {
517  operator FunctorTag();
518 
520  template<class T1, class T2>
521  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 == t2)
522  {
523  return t1 == t2;
524  }
525  };
526 
528  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
529  using EqualOf = BinaryJoin<Equal, AFunctor1, AFunctor2>;
530 
532  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
533  EqualOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator==(const ALHS& lhs, const ARHS& rhs)
534  {
535  return {toFunctor(lhs), toFunctor(rhs)};
536  }
537 
539  struct IsNaN {
541  operator FunctorTag();
542 
544  template<class T>
545  bool operator()(const T& t) const
546  {
547  return std::isnan(t);
548  }
549  };
550 
551  // ******************** Other operators are left as exercise ********************
552 
553  }
555 }
Filter< OperatorNot, Filter< types... >, VoidObserver > operator!(const Filter< types... > &filter)
Definition of the NOT operator ! for the Filter class.
Definition: Filter.h:583
Abstract base class for different kinds of events.
Generic functor to try to functors and choose the first to be applicable.
Definition: Functional.h:180
auto operator()(T &&... t) const -> decltype(this->impl(0, std::forward< T >(t)...))
Operator to dispatch to the two functors and returns the first applicable option.
Definition: Functional.h:224
Alternation()=default
Allow default construction.
AFunctor2 m_functor2
Memory for the second nested functor.
Definition: Functional.h:191
Alternation(const AFunctor1 &functor1, const AFunctor2 &functor2=AFunctor2())
Constructor from the nested functors.
Definition: Functional.h:198
AFunctor1 m_functor1
Memory for the first nested functor.
Definition: Functional.h:188
auto impl(long disfavouredTag, T &&... t) const -> decltype(m_functor2(std::forward< T >(t)...))
Implementation applying the second functor. Disfavoured option.
Definition: Functional.h:215
auto impl(int favouredTag, T &&... t) const -> decltype(m_functor1(std::forward< T >(t)...))
Implementation applying the first functor. Favoured option.
Definition: Functional.h:207
Functor factory turning a binary functor and two functors into a new functor which executes the binar...
Definition: Functional.h:127
auto operator()(const T &t) const -> decltype(m_binaryOp(m_functor1(t), m_functor2(t)))
Operator getting the result of the binary operation from one object transformed by the two functors.
Definition: Functional.h:172
BinaryJoin(const ABinaryOp &binaryOp, const AFunctor1 &functor1, const AFunctor2 &functor2)
Constructor from the nested functors.
Definition: Functional.h:136
BinaryJoin(const AFunctor1 &functor1, const AFunctor2 &functor2)
Constructor from the nested functors.
Definition: Functional.h:145
AFunctor2 m_functor2
Memory for the second nested functor.
Definition: Functional.h:160
BinaryJoin()=default
Allow default construction.
ABinaryOp m_binaryOp
Memory for the binary operation.
Definition: Functional.h:154
AFunctor1 m_functor1
Memory for the first nested functor.
Definition: Functional.h:157
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(m_binaryOp(m_functor1(t1), m_functor2(t2)))
Operator getting the result of the binary operation from two objects transformed by the two functors.
Definition: Functional.h:165
Functor to get the .clear() from an abitrary objects.
Definition: Functional.h:338
auto operator()(T &t) const -> decltype(t.clear())
Operator getting the .clear() of an abitrary object.
Definition: Functional.h:344
Functor factory from the functional composition of two functors.
Definition: Functional.h:87
auto operator()(const T &t) const -> decltype(m_functor1(m_functor2(t)))
Operator getting the result of the function composition.
Definition: Functional.h:118
Composition(const AFunctor2 &functor2)
Constructor from the nested functor.
Definition: Functional.h:95
Composition()=default
Allow default construction.
AFunctor2 m_functor2
Memory for the nested functor.
Definition: Functional.h:113
AFunctor1 m_functor1
Memory for the nested functor.
Definition: Functional.h:110
Composition(const AFunctor1 &functor1, const AFunctor2 &functor2)
Constructor from the first and the nested functor.
Definition: Functional.h:102
Generic functor to wrap a constant as a function.
Definition: Functional.h:39
T m_t
Memory for the constant to be returned.
Definition: Functional.h:60
Constant(const T &t)
Constructor from the constant value.
Definition: Functional.h:46
constexpr const T & operator()(const S &) const
Operator returning the constant.
Definition: Functional.h:53
Functor to get the referenced object from an abitrary objects.
Definition: Functional.h:390
auto operator()(const T &t) const -> decltype(*t)
Operator getting the referenced object of an abitrary object.
Definition: Functional.h:396
auto operator()(const T *t) const -> decltype(*t)
Specialisation for pointers to make an assertion that no nullptr is derefernced.
Definition: Functional.h:403
Binary functor for equality comparision of abitrary objects - equivalent to std::equal_to<> (c++14)
Definition: Functional.h:515
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1==t2)
Operator for equality comparision of an abitrary object.
Definition: Functional.h:521
Tag class to facilitate marking of class as a functor in the sense of this code.
Definition: FunctorTag.h:20
Functor to get the I part (as of std::get<I>) from an abitrary objects.
Definition: Functional.h:275
auto operator()(const T &t) const -> decltype(std::get< I >(t))
Operator getting the I part (as of std::get<I>) of an abitrary object.
Definition: Functional.h:281
Binary functor for greater comparision of abitrary objects - equivalent to std::greater<> (c++14)
Definition: Functional.h:489
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1 > t2)
Operator for greater comparision of an abitrary object.
Definition: Functional.h:495
Generic identity functor.
Definition: Functional.h:25
T && operator()(T &&t) const
Operator that just returns the object itself - gets me.
Definition: Functional.h:31
Functor to get the indirection from an abitrary objects.
Definition: Functional.h:421
auto operator()(const T &t) const -> decltype(*(t.operator->()))
Operator getting the indirection of an abitrary object.
Definition: Functional.h:427
const T & operator()(const T *t) const
Specialisation for pointers that indirect to themselves.
Definition: Functional.h:435
Unary functor for equality comparison to NAN.
Definition: Functional.h:539
bool operator()(const T &t) const
Operator for equality comparision to NaN.
Definition: Functional.h:545
Binary functor for less comparision of abitrary objects - equivalent to std::less<> (c++14)
Definition: Functional.h:461
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1< t2)
Operator for less comparision of an abitrary object.
Definition: Functional.h:467
Functor to get the logical negation from an abitrary objects.
Definition: Functional.h:363
auto operator()(const T &t) const -> decltype(not t)
Operator getting the logical negation of an abitrary object.
Definition: Functional.h:369
Functor to get the .size() from an abitrary objects.
Definition: Functional.h:318
auto operator()(const T &t) const -> decltype(t.size())
Operator getting the .size() of an abitrary object.
Definition: Functional.h:324
Functor returning void from an abitrary objects.
Definition: Functional.h:235
void operator()(T &&t) const
Operator always returning void.
Definition: Functional.h:241