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  // Because we can guarantee that entries will not overlap due
258  // to using the offset above, we do not need to call
259  // out.insert(...), which will unnecessarily merge entries.
260  // It is the user's responsibility to ensure that the
261  // map_vector entries are properly sorted.
262  out.append(in.begin(), in.end());
263  }
264  };
265  }
266 }
267 
268 // I.
269 template <typename CONTAINER>
271 art::concatContainers(CONTAINER& out, CONTAINER const& in)
272 {
274 }
275 // II.
276 template <typename CONTAINER>
278 art::concatContainers(CONTAINER& out, CONTAINER const& in)
279 {
280  out.insert(out.end(), in.begin(), in.end());
281 }
282 
283 // 1.
284 template <typename COLLECTION>
285 void
286 art::flattenCollections(std::vector<COLLECTION const*> const& in,
287  COLLECTION& out)
288 {
289  typename COLLECTION::size_type total_size = 0;
290  for (auto collptr : in) {
291  if (collptr != nullptr) {
292  total_size += collptr->size();
293  }
294  }
295  out.reserve(total_size);
296  for (auto collptr : in) {
297  if (collptr != nullptr) {
298  concatContainers(out, *collptr);
299  }
300  }
301 }
302 
303 // 2.
304 template <typename COLLECTION, typename OFFSETS>
305 void
306 art::flattenCollections(std::vector<COLLECTION const*> const& in,
307  COLLECTION& out,
308  OFFSETS& offsets)
309 {
310  offsets.clear();
311  offsets.reserve(in.size());
312  typename COLLECTION::size_type current_offset{};
313  for (auto collptr : in) {
314  if (collptr == nullptr)
315  continue;
316 
317  auto const delta = detail::mix_offset<COLLECTION>::offset(*collptr);
318  offsets.push_back(current_offset);
319  current_offset += delta;
320  }
321  flattenCollections<COLLECTION>(in, out); // 1.
322 }
323 
324 // 3.
325 template <typename T>
326 void
328  PtrVector<T>& out)
329 {
330  // Extra checks are required to verify that the PtrVectors are
331  // compatible.
332  if (!detail::verifyPtrCollection(in)) {
334  << "Attempt to flatten incompatible PtrVectors "
335  << "referring to different ProductIDs.\n";
336  }
337  flattenCollections<PtrVector<T>>(in, out); // 1
338 }
339 
340 // 4.
341 template <typename T, typename OFFSETS>
342 void
344  PtrVector<T>& out,
345  OFFSETS& offsets)
346 {
347  // Extra checks are required to verify that the PtrVectors are
348  // compatible.
349  if (!detail::verifyPtrCollection(in)) {
351  << "Attempt to flatten incompatible PtrVectors "
352  << "referring to different ProductIDs.\n";
353  }
354  flattenCollections<PtrVector<T>>(in, out, offsets); // 2.
355 }
356 
357 #endif /* art_Persistency_Common_CollectionUtilities_h */
358 
359 // Local Variables:
360 // mode: c++
361 // End:
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
intermediate_table::iterator iterator
static size_t offset(cet::map_vector< P > const &mv)
char(&)[2] yes_tag
struct vector vector
intermediate_table::const_iterator const_iterator
static size_t offset(C const &c)
size_t delta() const
Definition: map_vector.h:152
void flattenCollections(std::vector< COLLECTION const * > const &in, COLLECTION &out)
no_tag has_three_arg_insert_helper(...)
void append(InIter b, InIter e)
Definition: map_vector.h:499
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
static void concatenate(CONTAINER &out, CONTAINER const &in)
cet::LibraryManager dummy("noplugin")
constexpr unsigned long asInt() const noexcept
Definition: map_vector.h:44
no_tag has_two_arg_insert_helper(...)
std::enable_if_t< detail::has_two_arg_insert< CONTAINER >::value > concatContainers(CONTAINER &out, CONTAINER const &in)