Belle II Software development
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
17namespace 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}
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 arbitrary objects.
Definition: Functional.h:338
auto operator()(T &t) const -> decltype(t.clear())
Operator getting the .clear() of an arbitrary 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 arbitrary objects.
Definition: Functional.h:390
auto operator()(const T &t) const -> decltype(*t)
Operator getting the referenced object of an arbitrary object.
Definition: Functional.h:396
auto operator()(const T *t) const -> decltype(*t)
Specialisation for pointers to make an assertion that no nullptr is dereferenced.
Definition: Functional.h:403
Binary functor for equality comparison of arbitrary 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 comparison of an arbitrary 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 arbitrary 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 arbitrary object.
Definition: Functional.h:281
Binary functor for greater comparison of arbitrary 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 comparison of an arbitrary 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 arbitrary objects.
Definition: Functional.h:421
const T & operator()(const T *t) const
Specialisation for pointers that indirect to themselves.
Definition: Functional.h:435
auto operator()(const T &t) const -> decltype(*(t.operator->()))
Operator getting the indirection of an arbitrary object.
Definition: Functional.h:427
Unary functor for equality comparison to NAN.
Definition: Functional.h:539
bool operator()(const T &t) const
Operator for equality comparison to NaN.
Definition: Functional.h:545
Binary functor for less comparison of arbitrary 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 comparison of an arbitrary object.
Definition: Functional.h:467
Functor to get the logical negation from an arbitrary objects.
Definition: Functional.h:363
auto operator()(const T &t) const -> decltype(not t)
Operator getting the logical negation of an arbitrary object.
Definition: Functional.h:369
Functor to get the .size() from an arbitrary objects.
Definition: Functional.h:318
auto operator()(const T &t) const -> decltype(t.size())
Operator getting the .size() of an arbitrary object.
Definition: Functional.h:324
Functor returning void from an arbitrary objects.
Definition: Functional.h:235
void operator()(T &&t) const
Operator always returning void.
Definition: Functional.h:241