CollectionUtilities.h
Go to the documentation of this file.
1 #ifndef art_Persistency_Common_CollectionUtilities_h
2 #define art_Persistency_Common_CollectionUtilities_h
3 ////////////////////////////////////////////////////////////////////////
4 // CollectionUtilities.h
5 //
6 // A collection of possibly-useful free function templates for use with
7 // collections. In all the below signatures, the following variables are
8 // used:
9 //
10 // std::vector<COLLECTION<PROD> const*> const& in
11 //
12 // COLLECTION<PROD>& out
13 //
14 // OFFSET_CONTAINER<COLLECTION::size_type>& offsets; // Output.
15 //
16 // OFFSET_CONTAINER<COLLECTION::size_type> const& offsets; // Input.
17 //
18 // OFFSET_CONTAINER and COLLECTION are arbitrary (and not necessarily
19 // identical) container types which satisfy the constraints as specified
20 // below. Most people will probably want std::vector unless they wish to
21 // safely and efficiently expand or shrink their list often (by adding
22 // and removing items, for example).
23 //
24 // OFFSET_CONTAINER must support clear(), reserve() and push_back();
25 //
26 // COLLECTION must support insert() specifying iterators, const and
27 // non-const begin() and end(), and reserve(). Its iterators must support
28 // preincrement (operator++), comparisons and dereferencing (operator*).
29 //
30 // Some functions below expect COLLECTION to be a PtrVector<PROD> or
31 // other collection of Ptr<PROD>. This will be specified in the
32 // documentation for that function.
33 ////////////////////////////////////
34 //
35 // concatContainers(out, in)
36 //
37 // A general, simple function to append the contents of the container
38 // specified by the second argument to the container specified by the
39 // first.
40 //
41 // flattenCollections(...)
42 //
43 // A set of function templates to aid in the flattening of multiple
44 // collections (as represented usually as a vector of const pointers to
45 // colletions) into one collection, as required by acitivities such as
46 // product mixing. The interfaces are as follows:
47 //
48 // 1. Flatten a vector of simple collections to a single collection
49 // (*not* a PtrVector or other collection of Ptr -- cf 3. below or
50 // PtrRemapper).
51 //
52 // flattenCollections(in, out)
53 //
54 // 2. Flatten a vector of collections to a single collection, filling a
55 // vector of offests into the resultant collection (eg for use by
56 // PtrRemapper later).
57 //
58 //
59 // 3. Flatten a vector of *compatible* PtrVectors (ie they all point to
60 // the same product) to a single PtrVector. If they require remapping,
61 // do *not* use this method -- use PtrRemapper instead.
62 //
63 //
64 // 4. Flatten a vector of *compatible* PtrVectors, filling a vector of
65 // offsets into the resultant collection (eg for use by a
66 // PtrRemapper). This function is only useful in the (hopefully rare)
67 // case that one has a Ptr *into* a PtrVector.
68 //
69 ////////////////////////////////////////////////////////////////////////
70 
74 #include "cetlib/map_vector.h"
75 #include "cetlib/metaprogramming.h"
76 
77 #include <cstddef>
78 #include <type_traits>
79 #include <vector>
80 
81 namespace art {
82  // Forward declarations.
83  class EDProductGetter;
84 
85  // Template metaprogramming.
86  namespace detail {
87  using cet::no_tag;
88  using cet::yes_tag;
89 
90  template <typename T, typename InIter, void (T::*)(InIter, InIter)>
92  template <typename T, typename I>
94  template <typename T, typename I>
97  template <typename T>
99  static bool constexpr value =
100  sizeof(has_two_arg_insert_helper<T, typename T::const_iterator>(0)) ==
101  sizeof(yes_tag);
102  };
103 
104  template <typename T,
105  typename RET,
106  typename OutIter,
107  typename InIter,
108  RET (T::*)(OutIter, InIter, InIter)>
110  template <typename T, typename R, typename O, typename I>
112  template <typename T, typename R, typename O, typename I>
115  template <typename T>
117  static bool constexpr value =
119  void,
120  typename T::iterator,
121  typename T::const_iterator>(0)) ==
122  sizeof(yes_tag) ||
124  typename T::iterator,
125  typename T::const_iterator,
126  typename T::const_iterator>(0)) ==
127  sizeof(yes_tag);
128  };
129 
130  template <typename C>
131  struct mix_offset {
132  static size_t
133  offset(C const& c)
134  {
135  return c.size();
136  }
137  };
138 
139  template <typename P>
140  struct mix_offset<cet::map_vector<P>> {
141  static size_t
143  {
144  return mv.delta();
145  }
146  };
147  }
148 
149  // Append container in to container out.
150  // I.
151  template <typename CONTAINER>
153  concatContainers(CONTAINER& out, CONTAINER const& in);
154  // II.
155  template <typename CONTAINER>
157  concatContainers(CONTAINER& out, CONTAINER const& in);
158 
159  // 1.
160  template <typename COLLECTION>
161  void flattenCollections(std::vector<COLLECTION const*> const& in,
162  COLLECTION& out);
163 
164  // 2.
165  template <typename COLLECTION, typename OFFSETS>
166  void flattenCollections(std::vector<COLLECTION const*> const& in,
167  COLLECTION& out,
168  OFFSETS& offsets);
169 
170  // 3.
171  template <typename T>
172  void flattenCollections(std::vector<PtrVector<T> const*> const& in,
173  PtrVector<T>& out);
174 
175  // 4.
176  template <typename T, typename OFFSETS>
177  void flattenCollections(std::vector<PtrVector<T> const*> const& in,
178  PtrVector<T>& out,
179  OFFSETS& offsets);
180 }
181 
182 ////////////////////////////////////////////////////////////////////////
183 // No user-serviceable parts below.
184 ////////////////////////////////////////////////////////////////////////
185 
186 namespace art {
187  namespace detail {
188  // A. Verify a collection of PtrVector const*
189  template <typename T>
190  bool verifyPtrCollection(std::vector<art::PtrVector<T> const*> const& in);
191 
192  // B. Verify a collection (including PtrVector) of Ptrs.
193  template <typename iterator>
194  bool verifyPtrCollection(iterator beg,
195  iterator end,
196  art::ProductID id = {},
197  art::EDProductGetter const* getter = nullptr);
198  }
199 }
200 
201 // A.
202 template <typename T>
203 bool
205  std::vector<art::PtrVector<T> const*> const& in)
206 {
207  return verifyPtrCollection(in.begin(), in.end());
208 }
209 
210 // B.
211 template <typename iterator>
212 bool
214  iterator const end,
215  art::ProductID const id,
216  art::EDProductGetter const* getter)
217 {
218  if (beg == end)
219  return true;
220  if (!id.isValid()) {
221  id = (*beg).id();
222  }
223  if (!getter) {
224  getter = (*beg).productGetter();
225  }
226  for (iterator i = beg; i != end; ++i) {
227  if ((*i) != nullptr &&
228  !((*i)->productGetter() && (*i)->productGetter() == getter &&
229  (*i)->id().isValid() && (*i)->id() == id)) {
230  return false;
231  }
232  }
233  return true;
234 }
235 
236 namespace art {
237  namespace detail {
238  template <typename CONTAINER>
239  struct TwoArgInsert {
240  static void
241  concatenate(CONTAINER& out, CONTAINER const& in)
242  {
243  out.insert(in.begin(), in.end());
244  }
245  };
246 
247  template <typename T>
248  struct TwoArgInsert<cet::map_vector<T>> {
250  static void
252  {
253  // The offset is necessary for concatenating map_vectors so
254  // that all elements will be preserved.
255  auto const d = detail::mix_offset<mv_t>::offset(out);
256  for (auto& pr : in) {
257  pr.first = cet::map_vector_key{pr.first.asInt() + d};
258  }
259  out.insert(in.begin(), in.end());
260  }
261  };
262  }
263 }
264 
265 // I.
266 template <typename CONTAINER>
268 art::concatContainers(CONTAINER& out, CONTAINER const& in)
269 {
271 }
272 // II.
273 template <typename CONTAINER>
275 art::concatContainers(CONTAINER& out, CONTAINER const& in)
276 {
277  out.insert(out.end(), in.begin(), in.end());
278 }
279 
280 // 1.
281 template <typename COLLECTION>
282 void
283 art::flattenCollections(std::vector<COLLECTION const*> const& in,
284  COLLECTION& out)
285 {
286  typename COLLECTION::size_type total_size = 0;
287  for (auto collptr : in) {
288  if (collptr != nullptr) {
289  total_size += collptr->size();
290  }
291  }
292  out.reserve(total_size);
293  for (auto collptr : in) {
294  if (collptr != nullptr) {
295  concatContainers(out, *collptr);
296  }
297  }
298 }
299 
300 // 2.
301 template <typename COLLECTION, typename OFFSETS>
302 void
303 art::flattenCollections(std::vector<COLLECTION const*> const& in,
304  COLLECTION& out,
305  OFFSETS& offsets)
306 {
307  offsets.clear();
308  offsets.reserve(in.size());
309  typename COLLECTION::size_type current_offset{};
310  for (auto collptr : in) {
311  if (collptr == nullptr)
312  continue;
313 
314  auto const delta = detail::mix_offset<COLLECTION>::offset(*collptr);
315  offsets.push_back(current_offset);
316  current_offset += delta;
317  }
318  flattenCollections<COLLECTION>(in, out); // 1.
319 }
320 
321 // 3.
322 template <typename T>
323 void
324 art::flattenCollections(std::vector<PtrVector<T> const*> const& in,
325  PtrVector<T>& out)
326 {
327  // Extra checks are required to verify that the PtrVectors are
328  // compatible.
329  if (!detail::verifyPtrCollection(in)) {
331  << "Attempt to flatten incompatible PtrVectors "
332  << "referring to different ProductIDs.\n";
333  }
334  flattenCollections<PtrVector<T>>(in, out); // 1
335 }
336 
337 // 4.
338 template <typename T, typename OFFSETS>
339 void
340 art::flattenCollections(std::vector<PtrVector<T> const*> const& in,
341  PtrVector<T>& out,
342  OFFSETS& offsets)
343 {
344  // Extra checks are required to verify that the PtrVectors are
345  // compatible.
346  if (!detail::verifyPtrCollection(in)) {
348  << "Attempt to flatten incompatible PtrVectors "
349  << "referring to different ProductIDs.\n";
350  }
351  flattenCollections<PtrVector<T>>(in, out, offsets); // 2.
352 }
353 
354 #endif /* art_Persistency_Common_CollectionUtilities_h */
355 
356 // Local Variables:
357 // mode: c++
358 // End:
::xsd::cxx::tree::id< char, ncname > id
Definition: Database.h:165
static size_t offset(cet::map_vector< P > const &mv)
char(&)[2] yes_tag
double delta
Definition: runWimpSim.h:98
std::pair< iterator, bool > insert(value_type const &x)
Definition: map_vector.h:459
static size_t offset(C const &c)
size_t delta() const
Definition: map_vector.h:152
const double C
void flattenCollections(std::vector< COLLECTION const * > const &in, COLLECTION &out)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Definition: typedefs.hpp:11
no_tag has_three_arg_insert_helper(...)
const XML_Char int const XML_Char * value
Definition: expat.h:331
Float_t d
Definition: plot.C:236
bool verifyPtrCollection(std::vector< art::PtrVector< T > const * > const &in)
char(&)[1] no_tag
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
ifstream in
Definition: comparison.C:7
static void concatenate(CONTAINER &out, CONTAINER const &in)
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
no_tag has_two_arg_insert_helper(...)
std::enable_if_t< detail::has_two_arg_insert< CONTAINER >::value > concatContainers(CONTAINER &out, CONTAINER const &in)
typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData