LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
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 
5 #include "cetlib/container_algorithms.h"
6 #include "cetlib/map_vector.h"
7 #include "cetlib/metaprogramming.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 
34  using cet::enable_if_function_exists_t;
35 
36  template <typename T, typename = void>
37  struct has_aggregate : std::false_type {
38  };
39 
40  template <typename T>
41  struct has_aggregate<
42  T,
43  enable_if_function_exists_t<void (T::*)(T const&), &T::aggregate>>
44  : std::true_type {
45  };
46 
47  template <typename T>
48  struct has_aggregate<
49  T,
50  enable_if_function_exists_t<void (T::*)(T), &T::aggregate>>
51  : std::true_type {
52  };
53 
54  template <typename T, typename Enable = void>
55  struct CanBeAggregated : std::false_type {
56  static void
57  aggregate(T&, T const&)
58  {
60  << "Products of type \"" << cet::demangle_symbol(typeid(T).name())
61  << "\" cannot be aggregated.\n"
62  << "Please contact artists@fnal.gov.\n";
63  }
64  };
65 
66  // Arithmetic
67  template <typename T>
68  struct CanBeAggregated<T, std::enable_if_t<std::is_arithmetic<T>::value>>
69  : std::true_type {
70  static void
71  aggregate(T& p, T const other)
72  {
73  p += other;
74  }
75  };
76 
77  // User-defined
78  template <typename T>
79  struct CanBeAggregated<T, std::enable_if_t<has_aggregate<T>::value>>
80  : std::true_type {
81  static void
82  aggregate(T& p, T const& other)
83  {
84  p.aggregate(other);
85  }
86  };
87 
88  template <typename T>
89  struct CanBeAggregated<std::vector<T>> : std::true_type {
90  static void
91  aggregate(std::vector<T>& p, std::vector<T> const& other)
92  {
93  p.insert(p.cend(), other.cbegin(), other.cend());
94  }
95  };
96 
97  template <typename T>
98  struct CanBeAggregated<std::list<T>> : std::true_type {
99  static void
100  aggregate(std::list<T>& p, std::list<T> const& other)
101  {
102  p.insert(p.cend(), other.cbegin(), other.cend());
103  }
104  };
105 
106  template <typename T>
107  struct CanBeAggregated<std::deque<T>> : std::true_type {
108  static void
109  aggregate(std::deque<T>& p, std::deque<T> const& other)
110  {
111  p.insert(p.cend(), other.cbegin(), other.cend());
112  }
113  };
114 
115  // std::array not currently supported by ROOT6
116  template <typename T, size_t N>
117  struct CanBeAggregated<std::array<T, N>> : std::true_type {
118  static void
119  aggregate(std::array<T, N>& p, std::array<T, N> const& other)
120  {
121  cet::transform_all(p, other, std::begin(p), [](T t1, T const& t2) {
123  return t1;
124  });
125  }
126  };
127 
128  // Implementation details for Tuple
129  template <std::size_t>
131 
132  template <>
133  struct AggregateTuple<0u> {
134  template <typename Tuple>
135  static void
136  combine(Tuple&, Tuple const&)
137  {}
138  };
139 
140  template <std::size_t I>
141  struct AggregateTuple {
142  template <typename Tuple>
143  static void
144  combine(Tuple& p, Tuple const& other)
145  {
146  using elem_type = std::tuple_element_t<I, Tuple>;
148  std::get<I>(other));
150  }
151  };
152 
153  // std::tuple not currently supported by ROOT6
154  template <typename... ARGS>
155  struct CanBeAggregated<std::tuple<ARGS...>> : std::true_type {
156  static void
157  aggregate(std::tuple<ARGS...>& p, std::tuple<ARGS...> const& other)
158  {
159  AggregateTuple<sizeof...(ARGS) - 1>::combine(p, other);
160  }
161  };
162 
163  template <typename K, typename V>
164  struct CanBeAggregated<std::map<K, V>> : std::true_type {
165  static void
166  aggregate(std::map<K, V>& p, std::map<K, V> const& other)
167  {
168  // Maybe throw exception if insert fails.
169  p.insert(other.cbegin(), other.cend());
170  }
171  };
172 
173  template <typename K, typename V>
174  struct CanBeAggregated<std::pair<K, V>> : std::true_type {
175  static void
176  aggregate(std::pair<K, V>& p, std::pair<K, V> const& other)
177  {
178  CanBeAggregated<K>::aggregate(p.first, other.first);
179  CanBeAggregated<V>::aggregate(p.second, other.second);
180  }
181  };
182 
183  template <typename K, typename V>
184  struct CanBeAggregated<std::multimap<K, V>> : std::true_type {
185  static void
186  aggregate(std::multimap<K, V>& p, std::multimap<K, V> const& other)
187  {
188  p.insert(other.cbegin(), other.cend());
189  }
190  };
191 
192  template <typename T>
193  struct CanBeAggregated<std::set<T>> : std::true_type {
194  static void
195  aggregate(std::set<T>& p, std::set<T> const& other)
196  {
197  // Maybe throw exception if insert fails.
198  p.insert(other.cbegin(), other.cend());
199  }
200  };
201 
202  template <typename T>
203  struct CanBeAggregated<cet::map_vector<T>> : std::true_type {
204  static void
205  aggregate(cet::map_vector<T>& p, cet::map_vector<T> const& other)
206  {
207  // Maybe throw exception if insert fails.
208  p.insert(other.cbegin(), other.cend());
209  }
210  };
211 
212  // Discuss with stakeholders
213  template <>
214  struct CanBeAggregated<std::string> : std::true_type {
215  static void
216  aggregate(std::string& p, std::string const& other)
217  {
218  if (p != other)
220  << "Products of type \""
221  << cet::demangle_symbol(typeid(std::string).name())
222  << "\" cannot be aggregated unless their values are the same.\n"
223  << "Values presented were: \"" << p << "\" and \"" << other
224  << "\".\n";
225  }
226  };
227 
228  //==============================================================
229  // CLHEP specializations
230 
231  template <>
232  struct CanBeAggregated<CLHEP::HepVector> : std::true_type {
233  static void aggregate(CLHEP::HepVector& p, CLHEP::HepVector const& other);
234  };
235 
236  template <>
237  struct CanBeAggregated<CLHEP::Hep2Vector> : std::true_type {
238  static void aggregate(CLHEP::Hep2Vector& p,
239  CLHEP::Hep2Vector const& other);
240  };
241 
242  template <>
243  struct CanBeAggregated<CLHEP::Hep3Vector> : std::true_type {
244  static void aggregate(CLHEP::Hep3Vector& p,
245  CLHEP::Hep3Vector const& other);
246  };
247 
248  template <>
249  struct CanBeAggregated<CLHEP::HepLorentzVector> : std::true_type {
250  static void aggregate(CLHEP::HepLorentzVector& p,
251  CLHEP::HepLorentzVector const& other);
252  };
253 
254  template <>
255  struct CanBeAggregated<CLHEP::HepMatrix> : std::true_type {
256  static void aggregate(CLHEP::HepMatrix& p, CLHEP::HepMatrix const& other);
257  };
258 
259  template <>
260  struct CanBeAggregated<CLHEP::HepSymMatrix> : std::true_type {
261  static void aggregate(CLHEP::HepSymMatrix& p,
262  CLHEP::HepSymMatrix const& other);
263  };
264 
265  //==============================================================
266  // ROOT-TH1 specializations
267  //
268  // .. Do not include TH1.h! Adding the TH1.h header causes woe
269  // since it introduces a definition of a static variable of
270  // type TVersionCheck, whose constructor is defined in the
271  // ROOT_CORE library. This causes users to link essentially
272  // EVERYTHING against ROOT_CORE. This is not a problem for
273  // modules/source (they already depend on ROOT_CORE), but it
274  // would introduce an inherent dependency on ROOT for services
275  // as well. Fortunately, the std::is_base_of<Base,Derived>
276  // implementation only requires that Derived (T) be a complete
277  // type, and not that of Base (TH1).
278 
279  template <typename T>
280  struct CanBeAggregated<T, std::enable_if_t<std::is_base_of<TH1, T>::value>>
281  : std::true_type {
282  static void
283  aggregate(T& p, T const& other)
284  {
285  p.Add(&other);
286  }
287  };
288  }
289 }
290 
291 #endif /* canvas_Persistency_Common_detail_aggregate_h */
292 
293 // Local variables:
294 // mode: c++
295 // End:
TTree * t1
Definition: plottest35.C:26
static void aggregate(std::set< T > &p, std::set< T > const &other)
Definition: aggregate.h:195
STL namespace.
void * Tuple
Definition: DBFolder.h:13
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
static void aggregate(std::string &p, std::string const &other)
Definition: aggregate.h:216
static void combine(Tuple &, Tuple const &)
Definition: aggregate.h:136
static void aggregate(std::array< T, N > &p, std::array< T, N > const &other)
Definition: aggregate.h:119
TTree * t2
Definition: plottest35.C:36
static void aggregate(std::tuple< ARGS... > &p, std::tuple< ARGS... > const &other)
Definition: aggregate.h:157
static void aggregate(std::deque< T > &p, std::deque< T > const &other)
Definition: aggregate.h:109
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:100
static void combine(Tuple &p, Tuple const &other)
Definition: aggregate.h:144
static void aggregate(cet::map_vector< T > &p, cet::map_vector< T > const &other)
Definition: aggregate.h:205
HLT enums.
static void aggregate(std::multimap< K, V > &p, std::multimap< K, V > const &other)
Definition: aggregate.h:186
static void aggregate(std::map< K, V > &p, std::map< K, V > const &other)
Definition: aggregate.h:166
static void aggregate(T &, T const &)
Definition: aggregate.h:57
static void aggregate(std::vector< T > &p, std::vector< T > const &other)
Definition: aggregate.h:91
static void aggregate(std::pair< K, V > &p, std::pair< K, V > const &other)
Definition: aggregate.h:176