aggregate.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_detail_aggregate_h
2 #define canvas_Persistency_Common_detail_aggregate_h
3 
6 #include "cetlib/map_vector.h"
8 #include "cetlib_except/demangle.h"
9 
10 #include <typeinfo>
11 
12 #include <array>
13 #include <deque>
14 #include <list>
15 #include <map>
16 #include <set>
17 #include <utility>
18 #include <vector>
19 
20 namespace CLHEP {
21  class HepVector;
22  class Hep2Vector;
23  class Hep3Vector;
24  class HepLorentzVector;
25  class HepMatrix;
26  class HepSymMatrix;
27 }
28 
29 class TH1;
30 
31 namespace art {
32  namespace detail {
33 
35 
36  template <typename T, typename = void>
37  struct has_aggregate : std::false_type {};
38 
39  template <typename T>
40  struct has_aggregate<
41  T,
42  enable_if_function_exists_t<void (T::*)(T const&), &T::aggregate>>
43  : std::true_type {};
44 
45  template <typename T>
46  struct has_aggregate<
47  T,
48  enable_if_function_exists_t<void (T::*)(T), &T::aggregate>>
49  : std::true_type {};
50 
51  template <typename T, typename Enable = void>
52  struct CanBeAggregated : std::false_type {
53  static void
54  aggregate(T&, T const&)
55  {
57  << "Products of type \"" << cet::demangle_symbol(typeid(T).name())
58  << "\" cannot be aggregated.\n"
59  << "Please contact artists@fnal.gov.\n";
60  }
61  };
62 
63  // Arithmetic
64  template <typename T>
65  struct CanBeAggregated<T, std::enable_if_t<std::is_arithmetic<T>::value>>
66  : std::true_type {
67  static void
68  aggregate(T& p, T const other)
69  {
70  p += other;
71  }
72  };
73 
74  // User-defined
75  template <typename T>
76  struct CanBeAggregated<T, std::enable_if_t<has_aggregate<T>::value>>
77  : std::true_type {
78  static void
79  aggregate(T& p, T const& other)
80  {
81  p.aggregate(other);
82  }
83  };
84 
85  template <typename T>
86  struct CanBeAggregated<std::vector<T>> : std::true_type {
87  static void
88  aggregate(std::vector<T>& p, std::vector<T> const& other)
89  {
90  p.insert(p.cend(), other.cbegin(), other.cend());
91  }
92  };
93 
94  template <typename T>
95  struct CanBeAggregated<std::list<T>> : std::true_type {
96  static void
97  aggregate(std::list<T>& p, std::list<T> const& other)
98  {
99  p.insert(p.cend(), other.cbegin(), other.cend());
100  }
101  };
102 
103  template <typename T>
104  struct CanBeAggregated<std::deque<T>> : std::true_type {
105  static void
106  aggregate(std::deque<T>& p, std::deque<T> const& other)
107  {
108  p.insert(p.cend(), other.cbegin(), other.cend());
109  }
110  };
111 
112  // std::array not currently supported by ROOT6
113  template <typename T, size_t N>
114  struct CanBeAggregated<std::array<T, N>> : std::true_type {
115  static void
116  aggregate(std::array<T, N>& p, std::array<T, N> const& other)
117  {
118  cet::transform_all(p, other, std::begin(p), [](T t1, T const& t2) {
120  return t1;
121  });
122  }
123  };
124 
125  // Implementation details for Tuple
126  template <std::size_t>
128 
129  template <>
130  struct AggregateTuple<0u> {
131  template <typename Tuple>
132  static void
133  combine(Tuple&, Tuple const&)
134  {}
135  };
136 
137  template <std::size_t I>
138  struct AggregateTuple {
139  template <typename Tuple>
140  static void
141  combine(Tuple& p, Tuple const& other)
142  {
143  using elem_type = std::tuple_element_t<I, Tuple>;
145  std::get<I>(other));
147  }
148  };
149 
150  // std::tuple not currently supported by ROOT6
151  template <typename... ARGS>
152  struct CanBeAggregated<std::tuple<ARGS...>> : std::true_type {
153  static void
154  aggregate(std::tuple<ARGS...>& p, std::tuple<ARGS...> const& other)
155  {
156  AggregateTuple<sizeof...(ARGS) - 1>::combine(p, other);
157  }
158  };
159 
160  template <typename K, typename V>
161  struct CanBeAggregated<std::map<K, V>> : std::true_type {
162  static void
163  aggregate(std::map<K, V>& p, std::map<K, V> const& other)
164  {
165  // Maybe throw exception if insert fails.
166  p.insert(other.cbegin(), other.cend());
167  }
168  };
169 
170  template <typename K, typename V>
171  struct CanBeAggregated<std::pair<K, V>> : std::true_type {
172  static void
173  aggregate(std::pair<K, V>& p, std::pair<K, V> const& other)
174  {
175  CanBeAggregated<K>::aggregate(p.first, other.first);
176  CanBeAggregated<V>::aggregate(p.second, other.second);
177  }
178  };
179 
180  template <typename K, typename V>
181  struct CanBeAggregated<std::multimap<K, V>> : std::true_type {
182  static void
183  aggregate(std::multimap<K, V>& p, std::multimap<K, V> const& other)
184  {
185  p.insert(other.cbegin(), other.cend());
186  }
187  };
188 
189  template <typename T>
190  struct CanBeAggregated<std::set<T>> : std::true_type {
191  static void
192  aggregate(std::set<T>& p, std::set<T> const& other)
193  {
194  // Maybe throw exception if insert fails.
195  p.insert(other.cbegin(), other.cend());
196  }
197  };
198 
199  template <typename T>
200  struct CanBeAggregated<cet::map_vector<T>> : std::true_type {
201  static void
203  {
204  // Maybe throw exception if insert fails.
205  p.insert(other.cbegin(), other.cend());
206  }
207  };
208 
209  // Discuss with stakeholders
210  template <>
211  struct CanBeAggregated<std::string> : std::true_type {
212  static void
214  {
215  if (p != other)
217  << "Products of type \""
218  << cet::demangle_symbol(typeid(std::string).name())
219  << "\" cannot be aggregated unless their values are the same.\n"
220  << "Values presented were: \"" << p << "\" and \"" << other
221  << "\".\n";
222  }
223  };
224 
225  //==============================================================
226  // CLHEP specializations
227 
228  template <>
229  struct CanBeAggregated<CLHEP::HepVector> : std::true_type {
230  static void aggregate(CLHEP::HepVector& p, CLHEP::HepVector const& other);
231  };
232 
233  template <>
234  struct CanBeAggregated<CLHEP::Hep2Vector> : std::true_type {
235  static void aggregate(CLHEP::Hep2Vector& p,
236  CLHEP::Hep2Vector const& other);
237  };
238 
239  template <>
240  struct CanBeAggregated<CLHEP::Hep3Vector> : std::true_type {
241  static void aggregate(CLHEP::Hep3Vector& p,
242  CLHEP::Hep3Vector const& other);
243  };
244 
245  template <>
246  struct CanBeAggregated<CLHEP::HepLorentzVector> : std::true_type {
247  static void aggregate(CLHEP::HepLorentzVector& p,
249  };
250 
251  template <>
252  struct CanBeAggregated<CLHEP::HepMatrix> : std::true_type {
253  static void aggregate(CLHEP::HepMatrix& p, CLHEP::HepMatrix const& other);
254  };
255 
256  template <>
257  struct CanBeAggregated<CLHEP::HepSymMatrix> : std::true_type {
258  static void aggregate(CLHEP::HepSymMatrix& p,
259  CLHEP::HepSymMatrix const& other);
260  };
261 
262  //==============================================================
263  // ROOT-TH1 specializations
264  //
265  // .. Do not include TH1.h! Adding the TH1.h header causes woe
266  // since it introduces a definition of a static variable of
267  // type TVersionCheck, whose constructor is defined in the
268  // ROOT_CORE library. This causes users to link essentially
269  // EVERYTHING against ROOT_CORE. This is not a problem for
270  // modules/source (they already depend on ROOT_CORE), but it
271  // would introduce an inherent dependency on ROOT for services
272  // as well. Fortunately, the std::is_base_of<Base,Derived>
273  // implementation only requires that Derived (T) be a complete
274  // type, and not that of Base (TH1).
275 
276  template <typename T>
277  struct CanBeAggregated<T, std::enable_if_t<std::is_base_of<TH1, T>::value>>
278  : std::true_type {
279  static void
280  aggregate(T& p, T const& other)
281  {
282  p.Add(&other);
283  }
284  };
285  }
286 }
287 
288 #endif /* canvas_Persistency_Common_detail_aggregate_h */
289 
290 // Local variables:
291 // mode: c++
292 // End:
const XML_Char * name
Definition: expat.h:151
static void aggregate(std::set< T > &p, std::set< T > const &other)
Definition: aggregate.h:192
const_iterator cend() const noexcept
Definition: map_vector.h:228
const char * p
Definition: xmltok.h:285
std::pair< iterator, bool > insert(value_type const &x)
Definition: map_vector.h:459
enable_if_same_t< FT, decltype(f), R > enable_if_function_exists_t
static void aggregate(std::string &p, std::string const &other)
Definition: aggregate.h:213
static void combine(Tuple &, Tuple const &)
Definition: aggregate.h:133
double t2
static void aggregate(std::array< T, N > &p, std::array< T, N > const &other)
Definition: aggregate.h:116
auto transform_all(Container &, OutputIt, UnaryOp)
static void aggregate(std::tuple< ARGS... > &p, std::tuple< ARGS... > const &other)
Definition: aggregate.h:154
static void aggregate(std::deque< T > &p, std::deque< T > const &other)
Definition: aggregate.h:106
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
static void aggregate(std::list< T > &p, std::list< T > const &other)
Definition: aggregate.h:97
static void combine(Tuple &p, Tuple const &other)
Definition: aggregate.h:141
static void aggregate(cet::map_vector< T > &p, cet::map_vector< T > const &other)
Definition: aggregate.h:202
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
double T
Definition: Xdiff_gwt.C:5
static void aggregate(std::multimap< K, V > &p, std::multimap< K, V > const &other)
Definition: aggregate.h:183
static void aggregate(std::map< K, V > &p, std::map< K, V > const &other)
Definition: aggregate.h:163
static void aggregate(T &, T const &)
Definition: aggregate.h:54
typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData
static void aggregate(std::vector< T > &p, std::vector< T > const &other)
Definition: aggregate.h:88
const_iterator cbegin() const noexcept
Definition: map_vector.h:223
static void aggregate(std::pair< K, V > &p, std::pair< K, V > const &other)
Definition: aggregate.h:173
enum BeamMode string