Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Loki.hh
Go to the documentation of this file.
1 ///
2 /// @file Loki.hh
3 /// @brief Double dispatcher code based on examples from A.Alexandrescu's book
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #ifndef HAMMER_TOOLS_LOKI
13 #define HAMMER_TOOLS_LOKI
14 
15 #include<type_traits>
16 
17 #include "Hammer/Tools/Utils.hh"
18 
19 namespace Loki {
20 
21  template <typename Test, template <typename...> class Ref>
22  struct isSpecialization : std::false_type {};
23 
24  template <template <typename...> class Ref, typename... Args>
25  struct isSpecialization<Ref<Args...>, Ref> : std::true_type {};
26 
27 
28  template <typename... Ts>
29  struct TypeList {
30  static constexpr size_t size{ sizeof... (Ts) };
31  };
32 
34 
35  namespace TL {
36 
37  template<typename, typename>
38  struct IndexOf {};
39 
40  template<typename T, typename... Ts>
41  struct IndexOf<T, TypeList<T, Ts...>> : std::integral_constant<size_t, 0> {};
42 
43  template<typename T, typename TOther, typename... Ts>
44  struct IndexOf<T, TypeList<TOther, Ts...>> : std::integral_constant<size_t, 1 + IndexOf<T, TypeList<Ts...>>::value> {};
45 
46  }
47 
48  template<class Executor, class BaseLhs, class TypesLhs,
49  bool symmetric = true, class BaseRhs = BaseLhs,
50  class TypesRhs = TypesLhs, typename ResultType = void>
52 
53  private:
54 
55  template <bool swapArgs, class SomeLhs, class SomeRhs>
57  static ResultType DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec) {
58  return exec(lhs, rhs);
59  }
60  };
61  template <class SomeLhs, class SomeRhs>
62  struct InvocationTraits<true, SomeLhs, SomeRhs> {
63  static ResultType DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec) {
64  return exec(rhs, lhs);
65  }
66  };
67 
68  public:
69 
70  template <class SomeLhs>
71  static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, Executor& exec, NullType) {
72  return exec.error(lhs, rhs);
73  }
74 
75  template <class SomeLhs, class Head, class... Ts>
76  static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, Executor& exec, TypeList<Head, Ts...>) {
77  if (Head* p2 = dynamic_cast<Head*>(&rhs)) {
78  enum {
79  swapArgs = symmetric &&
82  };
83 
85 
86  return CallTraits::DoDispatch(lhs, *p2, exec);
87  }
88  return DispatchRhs(lhs, rhs, exec, TypeList<Ts...>());
89  }
90 
91  static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, Executor& exec, NullType) {
92  return exec.error(lhs, rhs);
93  }
94 
95  template <class Head, class... Ts>
96  static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, Executor& exec, TypeList<Head, Ts...>) {
97  if (Head* p1 = dynamic_cast<Head*>(&lhs)) {
98  return DispatchRhs(*p1, rhs, exec, TypesRhs());
99  }
100  return DispatchLhs(lhs, rhs, exec, TypeList<Ts...>());
101  }
102 
103  public:
104  static ResultType Go(BaseLhs& lhs, BaseRhs& rhs, Executor& exec) {
105  return DispatchLhs(lhs, rhs, exec, TypesLhs());
106  }
107 
108  };
109 
110  template <class Executor, class BaseLhs, class TypesLhs, typename ResultType = void>
112 
113  private:
114  template <class SomeLhs>
116  static ResultType DoDispatch(SomeLhs& lhs, Executor& exec) {
117  return exec(lhs);
118  }
119  };
120 
121  public:
122  static ResultType Dispatch(BaseLhs& lhs, Executor& exec, NullType) {
123  return exec.error(lhs);
124  }
125 
126  template <class Head, class... Ts>
127  static ResultType Dispatch(BaseLhs& lhs, Executor& exec, TypeList<Head, Ts...>) {
128  if (Head* p1 = dynamic_cast<Head*>(&lhs)) {
129  using CallTraits = InvocationTraits<Head>;
130 
131  return CallTraits::DoDispatch(*p1, exec);
132  }
133  return Dispatch(lhs, exec, TypeList<Ts...>());
134  }
135 
136  public:
137  static ResultType Go(BaseLhs& lhs, Executor& exec) {
138  return Dispatch(lhs, exec, TypesLhs());
139  }
140  };
141 } // namespace Loki
142 
143 #endif
static ResultType DispatchRhs(SomeLhs &lhs, BaseRhs &rhs, Executor &exec, TypeList< Head, Ts...>)
Definition: Loki.hh:76
static ResultType DoDispatch(SomeLhs &lhs, Executor &exec)
Definition: Loki.hh:116
static ResultType DispatchRhs(SomeLhs &lhs, BaseRhs &rhs, Executor &exec, NullType)
Definition: Loki.hh:71
static ResultType DispatchLhs(BaseLhs &lhs, BaseRhs &rhs, Executor &exec, TypeList< Head, Ts...>)
Definition: Loki.hh:96
static ResultType Go(BaseLhs &lhs, Executor &exec)
Definition: Loki.hh:137
static ResultType Dispatch(BaseLhs &lhs, Executor &exec, TypeList< Head, Ts...>)
Definition: Loki.hh:127
static constexpr size_t size
Definition: Loki.hh:30
static ResultType Go(BaseLhs &lhs, BaseRhs &rhs, Executor &exec)
Definition: Loki.hh:104
static ResultType DoDispatch(SomeLhs &lhs, SomeRhs &rhs, Executor &exec)
Definition: Loki.hh:63
static ResultType DispatchLhs(BaseLhs &lhs, BaseRhs &rhs, Executor &exec, NullType)
Definition: Loki.hh:91
static ResultType Dispatch(BaseLhs &lhs, Executor &exec, NullType)
Definition: Loki.hh:122
static ResultType DoDispatch(SomeLhs &lhs, SomeRhs &rhs, Executor &exec)
Definition: Loki.hh:57