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