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  } // namespace detail
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 } // namespace art
181 
182 ////////////////////////////////////////////////////////////////////////
183 // No user-serviceable parts below.
184 ////////////////////////////////////////////////////////////////////////
185 
186 namespace art::detail {
187  // A. Verify a collection of PtrVector const*
188  template <typename T>
189  bool verifyPtrCollection(std::vector<art::PtrVector<T> const*> const& in);
190 
191  // B. Verify a collection (including PtrVector) of Ptrs.
192  template <typename iterator>
193  bool verifyPtrCollection(iterator beg,
194  iterator end,
195  art::ProductID id = {},
196  art::EDProductGetter const* getter = nullptr);
197 }
198 
199 // A.
200 template <typename T>
201 bool
203  std::vector<art::PtrVector<T> const*> const& in)
204 {
205  return verifyPtrCollection(in.begin(), in.end());
206 }
207 
208 // B.
209 template <typename iterator>
210 bool
212  iterator const end,
213  art::ProductID const id,
214  art::EDProductGetter const* getter)
215 {
216  if (beg == end)
217  return true;
218  if (!id.isValid()) {
219  id = (*beg).id();
220  }
221  if (!getter) {
222  getter = (*beg).productGetter();
223  }
224  for (iterator i = beg; i != end; ++i) {
225  if ((*i) != nullptr &&
226  !((*i)->productGetter() && (*i)->productGetter() == getter &&
227  (*i)->id().isValid() && (*i)->id() == id)) {
228  return false;
229  }
230  }
231  return true;
232 }
233 
234 namespace art {
235  namespace detail {
236  template <typename CONTAINER>
237  struct TwoArgInsert {
238  static void
239  concatenate(CONTAINER& out, CONTAINER const& in)
240  {
241  out.insert(in.begin(), in.end());
242  }
243  };
244 
245  template <typename T>
246  struct TwoArgInsert<cet::map_vector<T>> {
248  static void
250  {
251  // The offset is necessary for concatenating map_vectors so
252  // that all elements will be preserved.
253  auto const d = detail::mix_offset<mv_t>::offset(out);
254  for (auto& pr : in) {
255  pr.first = cet::map_vector_key{pr.first.asInt() + d};
256  }
257  out.insert(in.begin(), in.end());
258  }
259  };
260  }
261 }
262 
263 // I.
264 template <typename CONTAINER>
266 art::concatContainers(CONTAINER& out, CONTAINER const& in)
267 {
269 }
270 // II.
271 template <typename CONTAINER>
273 art::concatContainers(CONTAINER& out, CONTAINER const& in)
274 {
275  out.insert(out.end(), in.begin(), in.end());
276 }
277 
278 // 1.
279 template <typename COLLECTION>
280 void
281 art::flattenCollections(std::vector<COLLECTION const*> const& in,
282  COLLECTION& out)
283 {
284  typename COLLECTION::size_type total_size = 0;
285  for (auto collptr : in) {
286  if (collptr != nullptr) {
287  total_size += collptr->size();
288  }
289  }
290  out.reserve(total_size);
291  for (auto collptr : in) {
292  if (collptr != nullptr) {
293  concatContainers(out, *collptr);
294  }
295  }
296 }
297 
298 // 2.
299 template <typename COLLECTION, typename OFFSETS>
300 void
301 art::flattenCollections(std::vector<COLLECTION const*> const& in,
302  COLLECTION& out,
303  OFFSETS& offsets)
304 {
305  offsets.clear();
306  offsets.reserve(in.size());
307  typename COLLECTION::size_type current_offset{};
308  for (auto collptr : in) {
309  if (collptr == nullptr)
310  continue;
311 
312  auto const delta = detail::mix_offset<COLLECTION>::offset(*collptr);
313  offsets.push_back(current_offset);
314  current_offset += delta;
315  }
316  flattenCollections<COLLECTION>(in, out); // 1.
317 }
318 
319 // 3.
320 template <typename T>
321 void
322 art::flattenCollections(std::vector<PtrVector<T> const*> const& in,
323  PtrVector<T>& out)
324 {
325  // Extra checks are required to verify that the PtrVectors are
326  // compatible.
327  if (!detail::verifyPtrCollection(in)) {
329  << "Attempt to flatten incompatible PtrVectors "
330  << "referring to different ProductIDs.\n";
331  }
332  flattenCollections<PtrVector<T>>(in, out); // 1
333 }
334 
335 // 4.
336 template <typename T, typename OFFSETS>
337 void
338 art::flattenCollections(std::vector<PtrVector<T> const*> const& in,
339  PtrVector<T>& out,
340  OFFSETS& offsets)
341 {
342  // Extra checks are required to verify that the PtrVectors are
343  // compatible.
344  if (!detail::verifyPtrCollection(in)) {
346  << "Attempt to flatten incompatible PtrVectors "
347  << "referring to different ProductIDs.\n";
348  }
349  flattenCollections<PtrVector<T>>(in, out, offsets); // 2.
350 }
351 
352 #endif /* art_Persistency_Common_CollectionUtilities_h */
353 
354 // Local Variables:
355 // mode: c++
356 // 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)
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