Belle II Software  release-05-02-19
Functional.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2016 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Oliver Frost *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 #pragma once
11 
12 #include <tracking/trackFindingCDC/utilities/FunctorTag.h>
13 
14 #include <type_traits>
15 #include <utility>
16 #include <cassert>
17 #include <cmath>
18 
19 namespace Belle2 {
24  namespace TrackFindingCDC {
25 
27  struct Id {
29  operator FunctorTag();
30 
32  template <class T>
33  T&& operator()(T&& t) const
34  {
35  return std::forward<T>(t);
36  }
37  };
38 
40  template<class T>
41  struct Constant {
43  operator FunctorTag();
44 
45  Constant() = default;
46 
48  explicit Constant(const T& t)
49  : m_t(t)
50  {
51  }
52 
54  template <class S>
55  constexpr const T& operator()(const S&) const
56  {
57  return m_t;
58  }
59 
60  private:
62  T m_t{};
63  };
64 
65 
66 
68  template<class T, class SFINAE = std::enable_if_t<not isFunctor<T>()> >
69  constexpr Constant<T> toFunctor(const T& t)
70  {
71  return Constant<T> {t};
72  }
73 
75  template<class AFunctor, class SFINAE = std::enable_if_t<isFunctor<AFunctor>()> >
76  constexpr const AFunctor & toFunctor(const AFunctor& get)
77  {
78  return get;
79  }
80 
82  template <class T>
83  using ToFunctor = typename std::decay<decltype(toFunctor(std::declval<T>()))>::type;
84 
85 
86 
88  template <class AFunctor1, class AFunctor2>
89  struct Composition {
91  operator FunctorTag();
92 
94  Composition() = default;
95 
97  explicit Composition(const AFunctor2& functor2)
98  : m_functor1()
99  , m_functor2(functor2)
100  {
101  }
102 
104  Composition(const AFunctor1& functor1, const AFunctor2& functor2)
105  : m_functor1(functor1)
106  , m_functor2(functor2)
107  {
108  }
109 
110  private: // Members here for lookup reasons
112  AFunctor1 m_functor1;
113 
115  AFunctor2 m_functor2;
116 
117  public:
119  template<class T>
120  auto operator()(const T& t) const -> decltype(m_functor1(m_functor2(t)))
121  {
122  return m_functor1(m_functor2(t));
123  }
124  };
125 
128  template <class ABinaryOp, class AFunctor1, class AFunctor2 = AFunctor1>
129  struct BinaryJoin : public ABinaryOp {
130  public:
132  operator FunctorTag();
133 
135  BinaryJoin() = default;
136 
138  BinaryJoin(const ABinaryOp& binaryOp, const AFunctor1& functor1, const AFunctor2& functor2)
139  : m_binaryOp(binaryOp)
140  , m_functor1(functor1)
141  , m_functor2(functor2)
142  {
143  }
144 
145 
147  BinaryJoin(const AFunctor1& functor1, const AFunctor2& functor2)
148  : m_binaryOp()
149  , m_functor1(functor1)
150  , m_functor2(functor2)
151  {
152  }
153 
154  private: // Members here for lookup reasons
156  ABinaryOp m_binaryOp;
157 
159  AFunctor1 m_functor1;
160 
162  AFunctor2 m_functor2;
163 
164  public:
166  template <class T1, class T2>
167  auto operator()(const T1& t1, const T2& t2) const -> decltype(m_binaryOp(m_functor1(t1), m_functor2(t2)))
168  {
169  return m_binaryOp(m_functor1(t1), m_functor2(t2));
170  }
171 
173  template <class T>
174  auto operator()(const T& t) const -> decltype(m_binaryOp(m_functor1(t), m_functor2(t)))
175  {
176  return m_binaryOp(m_functor1(t), m_functor2(t));
177  }
178  };
179 
181  template <class AFunctor1, class AFunctor2>
182  struct Alternation {
183 
184  public:
186  operator FunctorTag();
187 
188  private: // Members first for lookup reasons
190  AFunctor1 m_functor1;
191 
193  AFunctor2 m_functor2;
194 
195  public:
197  Alternation() = default;
198 
200  Alternation(const AFunctor1& functor1, const AFunctor2& functor2 = AFunctor2())
201  : m_functor1(functor1)
202  , m_functor2(functor2)
203  {
204  }
205 
206  public:
208  template <class... T>
209  auto impl(int favouredTag __attribute__((unused)), T&& ... t) const
210  -> decltype(m_functor1(std::forward<T>(t)...))
211  {
212  return m_functor1(std::forward<T>(t)...);
213  }
214 
216  template <class... T>
217  auto impl(long disfavouredTag __attribute__((unused)), T&& ... t) const
218  -> decltype(m_functor2(std::forward<T>(t)...))
219  {
220  return m_functor2(std::forward<T>(t)...);
221  }
222 
223  public:
225  template <class... T>
226  auto operator()(T&& ... t) const -> decltype(this->impl(0, std::forward<T>(t)...))
227  {
228  int dispatchTag = 0;
229  return impl(dispatchTag, std::forward<T>(t)...);
230  }
231  };
232 
233 
234  // ******************** (void)(?) ********************
235 
237  struct Void {
239  operator FunctorTag();
240 
242  template <class T>
243  void operator()(T&& t __attribute__((unused))) const
244  {
245  }
246  };
247 
249  template <class AFunctor = Id>
250  using VoidOf = Composition<Void, AFunctor>;
251 
253  template <class AFunctor>
255 
257  template<class AFunction, class... T>
258  void invokeIfApplicable(AFunction&& function, T&& ... t)
259  {
260  IfApplicable<AFunction> invokeIfApplicableImpl(std::forward<AFunction>(function));
261  invokeIfApplicableImpl(std::forward<T>(t)...);
262  }
263 
265  template<class ADefault, class AFunctor, class T>
266  ADefault getIfApplicable(AFunctor&& function, T&& obj, ADefault value)
267  {
268  Alternation<AFunctor, Constant<ADefault> > getIfApplicableImpl{std::forward<AFunctor>(function), Constant(value) };
269  return getIfApplicableImpl(std::forward<T>(obj));
270  }
271 
272 
273  // ******************** get<I>(?) ********************
274 
276  template<int I>
277  struct Get {
279  operator FunctorTag();
280 
282  template <class T>
283  auto operator()(const T& t) const -> decltype(std::get<I>(t))
284  {
285  using std::get;
286  return get<I>(t);
287  }
288  };
289 
291  template <int I, class AFunctor = Id>
292  using GetOf = Composition<Get<I>, AFunctor>;
293 
294 
295  // ******************** ?.first ********************
296 
299  using First = Get<0>;
300 
302  template<class AFunctor = Id>
303  using FirstOf = GetOf<0, AFunctor>;
304 
305 
306  // ******************** ?.second ********************
307 
310  using Second = Get<1>;
311 
313  template<class AFunctor = Id>
315 
316 
317  // ******************** ?.size() ********************
318 
320  struct Size {
322  operator FunctorTag();
323 
325  template <class T>
326  auto operator()(const T& t) const -> decltype(t.size())
327  {
328  return t.size();
329  }
330  };
331 
333  template <class AFunctor = Id>
335 
336 
337  // ******************** ?.clear() ********************
338 
340  struct Clear {
342  operator FunctorTag();
343 
345  template <class T>
346  auto operator()(T& t) const -> decltype(t.clear())
347  {
348  return t.clear();
349  }
350  };
351 
353  template <class AFunctor = Id>
355 
358 
360  static const ClearIfApplicable clearIfApplicable{};
361 
362  // ******************** not(?) ********************
363 
365  struct Not {
367  operator FunctorTag();
368 
370  template <class T>
371  auto operator()(const T& t) const -> decltype(not t)
372  {
373  return not t;
374  }
375  };
376 
378  template <class AFunctor = Id>
380 
382  template <class AFunctor, class SFINAE = std::enable_if_t<isFunctor<AFunctor>()> >
383  NotOf<AFunctor> operator!(const AFunctor& functor)
384  {
385  return NotOf<AFunctor> {functor};
386  }
387 
388 
389  // ******************** *? ********************
390 
392  struct Deref {
394  operator FunctorTag();
395 
397  template <class T>
398  auto operator()(const T& t) const -> decltype(*t)
399  {
400  return *t;
401  }
402 
404  template <class T>
405  auto operator()(const T* t) const -> decltype(*t)
406  {
407  assert(t != nullptr);
408  return *t;
409  }
410  };
411 
413  template <class AFunctor = Id>
415 
417  template <class AFunctor = Id>
419 
420  // ******************** *(?->) ********************
421 
423  struct Indirect {
425  operator FunctorTag();
426 
428  template <class T>
429  auto operator()(const T& t) const -> decltype(*(t.operator->()))
430  {
431  assert(t.operator->() != nullptr);
432  return *(t.operator->());
433  }
434 
436  template <class T>
437  const T& operator()(const T* t) const
438  {
439  assert(t != nullptr);
440  return *t;
441  }
442  };
443 
445  template <class AFunctor = Id>
447 
449  template <class AFunctor = Id>
451 
456  template <class AFunctor>
458  // using MayIndirectTo = AFunctor;
459 
460  // ******************** ? < ? aka less ********************
461 
463  struct Less {
465  operator FunctorTag();
466 
468  template<class T1, class T2>
469  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 < t2)
470  {
471  return t1 < t2;
472  }
473  };
474 
476  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
478 
480  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
481  LessOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator<(const ALHS& lhs, const ARHS& rhs)
482  {
483  return {toFunctor(lhs), toFunctor(rhs)};
484  }
485 
486 
487 
488  // ******************** ? > ? aka greater ********************
489 
491  struct Greater {
493  operator FunctorTag();
494 
496  template<class T1, class T2>
497  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 > t2)
498  {
499  return t1 > t2;
500  }
501  };
502 
504  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
506 
508  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
509  GreaterOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator>(const ALHS& lhs, const ARHS& rhs)
510  {
511  return {toFunctor(lhs), toFunctor(rhs)};
512  }
513 
514  // ******************** ? == ? aka equal_to ********************
515 
517  struct Equal {
519  operator FunctorTag();
520 
522  template<class T1, class T2>
523  auto operator()(const T1& t1, const T2& t2) const -> decltype(t1 == t2)
524  {
525  return t1 == t2;
526  }
527  };
528 
530  template <class AFunctor1 = Id, class AFunctor2 = AFunctor1>
532 
534  template <class ALHS, class ARHS, class SFINAE = std::enable_if_t<isFunctor<ALHS>() or isFunctor<ARHS>()>>
535  EqualOf<ToFunctor<ALHS>, ToFunctor<ARHS> > operator==(const ALHS& lhs, const ARHS& rhs)
536  {
537  return {toFunctor(lhs), toFunctor(rhs)};
538  }
539 
541  struct IsNaN {
543  operator FunctorTag();
544 
546  template<class T>
547  bool operator()(const T& t) const
548  {
549  return std::isnan(t);
550  }
551  };
552 
553  // ******************** Other operators are left as exercise ********************
554 
555  }
557 }
Belle2::TrackFindingCDC::Composition::m_functor2
AFunctor2 m_functor2
Memory for the nested functor.
Definition: Functional.h:123
Belle2::TrackFindingCDC::BinaryJoin::m_binaryOp
ABinaryOp m_binaryOp
Memory for the binary operation.
Definition: Functional.h:164
Belle2::TrackFindingCDC::Composition::operator()
auto operator()(const T &t) const -> decltype(m_functor1(m_functor2(t)))
Operator getting the result of the function composition.
Definition: Functional.h:128
Belle2::TrackFindingCDC::BinaryJoin
Functor factory turning a binary functor and two functors into a new functor which executes the binar...
Definition: Functional.h:137
Belle2::TrackFindingCDC::Composition::Composition
Composition()=default
Allow default construction.
Belle2::TrackFindingCDC::Composition::m_functor1
AFunctor1 m_functor1
Memory for the nested functor.
Definition: Functional.h:120
Belle2::TrackFindingCDC::Void::operator()
void operator()(T &&t __attribute__((unused))) const
Operator always returning void.
Definition: Functional.h:251
Belle2::TrackFindingCDC::Equal
Binary functor for equality comparision of abitrary objects - equivalent to std::equal_to<> (c++14)
Definition: Functional.h:525
Belle2::TrackFindingCDC::Alternation::Alternation
Alternation()=default
Allow default construction.
Belle2::TrackFindingCDC::Alternation
Generic functor to try to functors and choose the first to be applicable.
Definition: Functional.h:190
Belle2::TrackFindingCDC::Get
Functor to get the I part (as of std::get<I>) from an abitrary objects.
Definition: Functional.h:285
Belle2::TrackFindingCDC::Not::operator()
auto operator()(const T &t) const -> decltype(not t)
Operator getting the logical negation of an abitrary object.
Definition: Functional.h:379
Belle2::TrackFindingCDC::BinaryJoin::BinaryJoin
BinaryJoin()=default
Allow default construction.
Belle2::TrackFindingCDC::BinaryJoin::m_functor1
AFunctor1 m_functor1
Memory for the first nested functor.
Definition: Functional.h:167
Belle2::TrackFindingCDC::Alternation::m_functor2
AFunctor2 m_functor2
Memory for the second nested functor.
Definition: Functional.h:201
Belle2::TrackFindingCDC::Alternation::operator()
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:234
Belle2::TrackFindingCDC::BinaryJoin::operator()
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:175
Belle2::TrackFindingCDC::Alternation::m_functor1
AFunctor1 m_functor1
Memory for the first nested functor.
Definition: Functional.h:198
Belle2::TrackFindingCDC::Id::operator()
T && operator()(T &&t) const
Operator that just returns the object itself - gets me.
Definition: Functional.h:41
Belle2::TrackFindingCDC::Alternation::impl
auto impl(int favouredTag __attribute__((unused)), T &&... t) const -> decltype(m_functor1(std::forward< T >(t)...))
Implementation applying the first functor. Favoured option.
Definition: Functional.h:217
Belle2::TrackFindingCDC::Constant
Generic functor to wrap a constant as a function.
Definition: Functional.h:49
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TrackFindingCDC::Size
Functor to get the .size() from an abitrary objects.
Definition: Functional.h:328
Belle2::TrackFindingCDC::Constant::m_t
T m_t
Memory for the constant to be returned.
Definition: Functional.h:70
Belle2::TrackFindingCDC::FunctorTag
Tag class to facilitate marking of class as a functor in the sense of this code.
Definition: FunctorTag.h:30
Belle2::TrackFindingCDC::Clear::operator()
auto operator()(T &t) const -> decltype(t.clear())
Operator getting the .clear() of an abitrary object.
Definition: Functional.h:354
Belle2::TrackFindingCDC::Equal::operator()
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1==t2)
Operator for equality comparision of an abitrary object.
Definition: Functional.h:531
Belle2::TrackFindingCDC::Indirect::operator()
auto operator()(const T &t) const -> decltype(*(t.operator->()))
Operator getting the indirection of an abitrary object.
Definition: Functional.h:437
Belle2::TrackFindingCDC::Void
Functor returning void from an abitrary objects.
Definition: Functional.h:245
Belle2::operator!
Filter< OperatorNot, Filter< types... >, VoidObserver > operator!(const Filter< types... > &filter)
Definition of the NOT operator ! for the Filter class.
Definition: Filter.h:593
Belle2::TrackFindingCDC::Get::operator()
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:291
Belle2::TrackFindingCDC::Size::operator()
auto operator()(const T &t) const -> decltype(t.size())
Operator getting the .size() of an abitrary object.
Definition: Functional.h:334
Belle2::TrackFindingCDC::Deref
Functor to get the referenced object from an abitrary objects.
Definition: Functional.h:400
Belle2::TrackFindingCDC::Greater::operator()
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1 > t2)
Operator for greater comparision of an abitrary object.
Definition: Functional.h:505
Belle2::TrackFindingCDC::Deref::operator()
auto operator()(const T &t) const -> decltype(*t)
Operator getting the referenced object of an abitrary object.
Definition: Functional.h:406
Belle2::TrackFindingCDC::Greater
Binary functor for greater comparision of abitrary objects - equivalent to std::greater<> (c++14)
Definition: Functional.h:499
Belle2::TrackFindingCDC::Less::operator()
auto operator()(const T1 &t1, const T2 &t2) const -> decltype(t1< t2)
Operator for less comparision of an abitrary object.
Definition: Functional.h:477
Belle2::TrackFindingCDC::BinaryJoin::m_functor2
AFunctor2 m_functor2
Memory for the second nested functor.
Definition: Functional.h:170
Belle2::TrackFindingCDC::Composition
Functor factory from the functional composition of two functors.
Definition: Functional.h:97
Belle2::TrackFindingCDC::Constant::operator()
constexpr const T & operator()(const S &) const
Operator returning the constant.
Definition: Functional.h:63
Belle2::TrackFindingCDC::Less
Binary functor for less comparision of abitrary objects - equivalent to std::less<> (c++14)
Definition: Functional.h:471
Belle2::TrackFindingCDC::Not
Functor to get the logical negation from an abitrary objects.
Definition: Functional.h:373
Belle2::TrackFindingCDC::Clear
Functor to get the .clear() from an abitrary objects.
Definition: Functional.h:348
Belle2::TrackFindingCDC::IsNaN::operator()
bool operator()(const T &t) const
Operator for equality comparision to NaN.
Definition: Functional.h:555
Belle2::TrackFindingCDC::IsNaN
Unary functor for equality comparison to NAN.
Definition: Functional.h:549
Belle2::TrackFindingCDC::Indirect
Functor to get the indirection from an abitrary objects.
Definition: Functional.h:431