LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PtrRemapper.h
Go to the documentation of this file.
1 #ifndef art_Framework_Core_PtrRemapper_h
2 #define art_Framework_Core_PtrRemapper_h
3 // PtrRemapper
5 //
6 // Class to aid in remapping Ptrs and ProductPtrs in various settings
7 // from items in one branch to (presumably the equivalent) items in
8 // another branch of the same type.
9 //
10 // This class is primarily for use in product mixing and will be
11 // properly initialized by the time it is provided as an argument to
12 // the user-supplied mixing function.
13 //
14 // PtrRemapper is a function object, so all of its work is done with
15 // the apply operator -- operator(). This means that if your mixing
16 // function has an argument (e.g.)
17 //
18 // art::PtrRemapper const& remap
19 //
20 // then the usage is:
21 //
22 // remap(...)
23 //
24 // There are several signatures to operator() and because they are all
25 // templates, they can look fairly impenetrable. It is recommended
26 // therefore to use this header documentation to decide what signature
27 // is most appropriate for your use rather than looking below at the
28 // prototypes or the implementation: there really are "No
29 // User-serviceable Parts."
30 //
31 // Notes common to several signatures.
32 //
33 // * With the exception of the (rarely required) signature 10 (see its
34 // specific documentation), all template arguments are deducible from
35 // the function arguments and therefore it is not necessary to specify
36 // them in <>.
37 //
38 // * Commonly-used arguments:
39 //
40 // * std::vector<COLLECTION<PROD> const*> const& in
41 //
42 // * OutIter& out
43 //
44 // OutIter is a variable of category insert_iterator (usually
45 // created by, for instance std::back_inserter(container)) into a
46 // container of Ptr (either PtrVector or some other collection of
47 // Ptr).
48 //
49 // * offset is a single offset into the container into which the
50 // Ptr points. It should be of type
51 // convertible-to-container::size_type.
52 //
53 // * offsets is an arbitrary container of such offsets as described
54 // in the documentation in
55 // art/Persistency/Common/CollectionUtilities.h.
56 //
57 // ------------------
58 // art::Ptr remapping
59 // ------------------
60 //
61 // Available signatures to operator() and example usage:
62 //
63 // 1. Remap a single Ptr.
64 //
65 // Ptr<A> newPtr{remap(oldPtr, offset)};
66 //
67 // 2. Remap a single PtrVector.
68 //
69 // PtrVector<A> newPV{remap(oldPV, offset)};
70 //
71 // 3. Remap a compatible collection (including PtrVector) of Ptr
72 // providing begin, end iterators. (This will also remap a compatible
73 // collection of PtrVector, but not of PtrVector const* -- for the
74 // latter, see 4-10.)
75 //
76 // PtrVector<A> newPV;
77 // remap(oldPV.begin(),
78 // oldPV.end(),
79 // std::back_inserter(newPV),
80 // offset);
81 //
82 // 4. Remap and flatten a set of products which are containers of
83 // Ptrs (which includes PtrVector).
84 //
85 // remap(in, out, offsets)
86 //
87 // where offsets is likely calculated by the appropriate call to
88 // art::flattenCollections. See
89 // art/Persistency/Common/CollectionUtilities for details.
90 //
91 // 5. Remap and flatten a set of containers of Ptrs (including
92 // PtrVector) which may be obtained from a component of the provided
93 // product. Provide a free function of the correct signature to return
94 // a reference to the container of Ptrs given a secondary product,
95 // e.g.:
96 //
97 // PtrVector<B> const& myfunc(A const* prod) {
98 // return prod->myBs();
99 // }
100 //
101 // remap(in, out, offsets, &myfunc);
102 //
103 // 6. Remap and flatten a set of containers of Ptrs (including
104 // PtrVector) which may be obtained from a component of the provided
105 // product. Provide the name of a member function of the provided
106 // product which is an accessor for the container (taking no
107 // arguments).
108 //
109 // remap(in, out, offsets, &A::myBs);
110 //
111 // 7. Remap and flatten a set of containers of Ptrs (including
112 // PtrVector) which may be obtained from a component of the provided
113 // product. Provide the name of a member datum of the provided product
114 // which is the container.
115 //
116 // remap(in, out, offsets, &A::myBs_);
117 //
118 // 8. Remap and flatten a set of containers of Ptrs (including
119 // PtrVector) which is a component of the provided product using the
120 // provided accessor member function of a class which is not the
121 // product.
122 //
123 // class Aprocessor {
124 // public:
125 // B const& myBs(A const*);
126 // };
127 //
128 // Aprocessor myAp;
129 //
130 // remap(in, out, offsets, Aprocessor::myBs, myAp);
131 //
132 // Note: if the compiler complains about an unresolved overload set
133 // for this signature, try an explicit:
134 //
135 // const_cast<Aprocessor&>(myAp);
136 //
137 // 9. Remap and flatten a set of containers of Ptrs (including
138 // PtrVector) which is a component of the provided product using the
139 // provided const accessor member function of a class which is not the
140 // product.
141 //
142 // class Aprocessor {
143 // public:
144 // B const& myBs(A const*) const;
145 // };
146 //
147 // Aprocessor myAp;
148 //
149 // remap(in, out, offsets, Aprocessor::myBs, myAp);
150 //
151 // Note: if the compiler complains about an unresolved overload set
152 // for this signature, try an explicit:
153 //
154 // const_cast<Aprocessor const&>(myAp);
155 //
156 // 10. More general version of 5-9. that takes a final argument which is
157 // of arbitrary type provided it or its operator() has the correct
158 // signature. The drawback is that one of the template arguments (CONT,
159 // specifying the type of the collection of Ptrs you wish to remap) is
160 // not deducible, meaning that instead of:
161 //
162 // remap(...);
163 //
164 // one must type (e.g.):
165 //
166 // remap.operator()<std::vector<art::Ptr<B> > >(...)
167 //
168 // Therefore, 4-9. are the recommended signatures for
169 // straightforward client code -- this one is provided for maximum
170 // flexibility.
171 //
172 // -------------------------
173 // art::ProductPtr remapping
174 // -------------------------
175 //
176 // ProductPtrs are simpler objects that require no offset--only the
177 // internal product ID must be adjusted. There is therefore a limited
178 // set of remapping facilities for them.
179 //
180 // 11. Remap a single art::ProductPtr is achieved via:
181 //
182 // ProductPtr<A> newProductPtr{remap(oldProductPtr)};
183 //
184 // 12. Remap a collection of art::ProductPtrs to a single
185 // art::ProductPtr. The requirement is that all art::ProductPtrs in
186 // the collection must refer to the same product.
187 //
188 // ProductPtr<A> newProductPtr{remap(in)};
189 //
190 // 13. Remap a collection of ProductPtrs which may be obtained from a
191 // component of the provided product. Provide the name of a member
192 // datum of the provided product which is the container.
193 //
194 // ProductPtr<A> newProductPtr{remap(in, &A::myProductPtr_)};
195 //
196 // 14. Remap a collection of ProductPtrs which may be obtained from a
197 // component of the provided product using the provided accessor
198 // member function of the class (taking no arguments).
199 //
200 // ProductPtr<A> newProductPtr{remap(in, &A::myProductPtr)};
201 //
203 
211 #include "cetlib/exempt_ptr.h"
212 
213 #include <map>
214 
215 namespace art {
216  class PtrRemapper;
217  class ProdToProdMapBuilder;
218 
219  namespace PtrRemapperDetail {
220  // Function template used by 4.
221  template <typename PROD>
222  PROD const&
223  simpleProdReturner(PROD const* prod)
224  {
225  return *prod;
226  }
227 
228  // Function object used by 10.
229  template <typename CONT, typename PROD, typename CALLBACK>
230  class ContReturner {
231  public:
232  explicit ContReturner(CALLBACK callback) : callback_(callback) {}
233  CONT const&
234  operator()(PROD const* prod) const
235  {
236  return callback_(prod);
237  }
238 
239  private:
240  CALLBACK callback_;
241  };
242 
243  template <typename CONT, typename PROD>
244  class ContReturner<CONT, PROD, CONT const& (PROD::*)() const> {
245  public:
246  using CALLBACK = CONT const& (PROD::*)() const;
247  explicit ContReturner(CALLBACK callback) : callback_(callback) {}
248  CONT const&
249  operator()(PROD const* prod) const
250  {
251  return (prod->*callback_)();
252  }
253 
254  private:
256  };
257 
258  template <typename CONT, typename PROD>
259  class ContReturner<CONT, PROD, CONT const PROD::*> {
260  public:
261  using CALLBACK = CONT const PROD::*;
262  explicit ContReturner(CALLBACK callback) : callback_(callback) {}
263  CONT const&
264  operator()(PROD const* prod) const
265  {
266  return prod->*callback_;
267  }
268 
269  private:
271  };
272  } // namespace PtrRemapperDetail
273 } // namespace art
274 
276 public:
278  // Signatures for operator() -- see documentation at top of header.
279 
280  // --------------
281  // Ptr remappings
282  // --------------
283 
284  // 1.
285  template <typename PROD, typename SIZE_TYPE>
286  Ptr<PROD> operator()(Ptr<PROD> const& oldPtr, SIZE_TYPE offset) const;
287 
288  // 2.
289  template <typename PROD, typename SIZE_TYPE>
291  SIZE_TYPE offset) const;
292 
293  // 3.
294  template <typename InIter, typename OutIter, typename SIZE_TYPE>
295  void operator()(InIter beg, InIter end, OutIter out, SIZE_TYPE offset) const;
296 
297  // 4.
298  template <typename OutIter, typename PROD, typename OFFSETS>
299  void operator()(std::vector<PROD const*> const& in,
300  OutIter out,
301  OFFSETS const& offsets) const;
302 
303  // 5.
304  template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
305  void operator()(std::vector<PROD const*> const& in,
306  OutIter out,
307  OFFSETS const& offsets,
308  CONT const& (*extractor)(PROD const*)) const;
309 
310  // 6.
311  template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
312  void operator()(std::vector<PROD const*> const& in,
313  OutIter out,
314  OFFSETS const& offsets,
315  CONT const& (PROD::*extractor)() const) const;
316 
317  // 7.
318  template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
319  void operator()(std::vector<PROD const*> const& in,
320  OutIter out,
321  OFFSETS const& offsets,
322  CONT const PROD::*data) const;
323 
324  // 8.
325  template <typename PROD,
326  typename OutIter,
327  typename CONT,
328  typename X,
329  typename OFFSETS>
330  void operator()(std::vector<PROD const*> const& in,
331  OutIter out,
332  OFFSETS const& offsets,
333  CONT const& (X::*extractor)(PROD const*),
334  X& x) const;
335 
336  // 9.
337  template <typename PROD,
338  typename OutIter,
339  typename CONT,
340  typename X,
341  typename OFFSETS>
342  void operator()(std::vector<PROD const*> const& in,
343  OutIter out,
344  OFFSETS const& offsets,
345  CONT const& (X::*extractor)(PROD const*) const,
346  X const& x) const;
347 
348  // 10.
349  template <typename CONT,
350  typename CALLBACK,
351  typename OutIter,
352  typename PROD,
353  typename OFFSETS>
354  void operator()(std::vector<PROD const*> const& in,
355  OutIter out,
356  OFFSETS const& offsets,
357  CALLBACK extractor) const;
358 
359  // ---------------------
360  // ProductPtr remappings
361  // ---------------------
362 
363  // 11.
364  template <typename PROD>
365  ProductPtr<PROD> operator()(ProductPtr<PROD> const& oldPtr) const;
366 
367  // 12.
368  template <typename PROD>
370  std::vector<ProductPtr<PROD> const*> const& in) const;
371 
372  // 13.
373  template <typename PROD, typename T>
374  ProductPtr<T> operator()(std::vector<PROD const*> const& in,
375  ProductPtr<T> const PROD::*data) const;
376 
377  // 14.
378  template <typename PROD, typename T>
379  ProductPtr<T> operator()(std::vector<PROD const*> const& in,
380  ProductPtr<T> const& (PROD::*extractor)()
381  const) const;
382 
383 private:
384  friend class ProdToProdMapBuilder;
385  using ProdTransMap_t = std::map<ProductID, ProductID>;
386 
387  RefCore newRefCore_(ProductID const incomingProductID) const;
388 
389  template <typename PROD>
390  static ProductPtr<PROD>
392  {
393  if (old == ProductPtr<PROD>{} or result == old) {
394  return result;
395  }
397  << "PtrRemapper: cannot create output "
398  << TypeID{typeid(ProductPtr<PROD>)}.className()
399  << "\ndue to conflicting IDs in input ProductPtrs: " << old.id()
400  << " vs. " << result.id() << "\nContact artists@fnal.gov for guidance.\n";
401  }
402 
403  template <typename T>
404  static auto
406  {
408  << "PtrRemapper: cannot create output "
409  << TypeID{typeid(T)}.className() << " with ProductID: " << id
410  << "\nbecause the product is not known. Perhaps the output product "
411  "was misspecified for product mixing.\n";
412  }
413 
414  // The following data members are filled by
415  // ProdToProdBuilder::populateRemapper, *not* by PtrRemapper.
416  ProdTransMap_t prodTransMap_{};
417  cet::exempt_ptr<Event const> event_{nullptr};
418 };
419 
420 // -------------------
421 // art::Ptr remappings
422 // -------------------
423 
424 // 1.
425 template <typename PROD, typename SIZE_TYPE>
428  SIZE_TYPE const offset) const
429 {
430  if (!oldPtr.id().isValid() || oldPtr.isNull()) {
431  return {};
432  }
433 
434  auto core = newRefCore_(oldPtr.id());
435  if (core.productGetter()) {
436  return Ptr<PROD>{core.id(), oldPtr.key() + offset, core.productGetter()};
437  }
438 
439  throw unknownProduct_<Ptr<PROD>>(core.id());
440 }
441 
442 // 2.
443 template <typename PROD, typename SIZE_TYPE>
446  SIZE_TYPE const offset) const
447 {
448  PtrVector<PROD> result;
449  result.reserve(old.size());
450  this->operator()(old.begin(),
451  old.end(),
452  std::back_inserter(result),
453  offset); // 3.
454  return result;
455 }
456 
457 // 3.
458 template <typename InIter, typename OutIter, typename SIZE_TYPE>
459 void
461  InIter const end,
462  OutIter out,
463  SIZE_TYPE const offset) const
464 {
465  // Need to assume that all Ptr containers and consistent internally
466  // and with each other due to a lack of productGetters.
467 
468  // Not using transform here allows instantiation for iterator to
469  // collection of Ptr or collection of PtrVector.
470  for (auto i = beg; i != end; ++i) {
471  // Note: this could be signature 1 OR 2 of operator(). If the user
472  // calls this signature (3) with iterators into a collection of
473  // PtrVector, then the call order will be 3, 2, 3, 1 due to the
474  // templates that will be instantiated i.e. the relationship
475  // between signatures 2 and 3 is *not* infinitely recursive.
476  *out++ = this->operator()(*i, offset); // 1 OR 2.
477  }
478 }
479 
480 // 4.
481 template <typename OutIter, typename PROD, typename OFFSETS>
482 void
483 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
484  OutIter out,
485  OFFSETS const& offsets) const
486 {
487  this->operator()(in,
488  out,
489  offsets,
490  PtrRemapperDetail::simpleProdReturner<PROD>); // 5.
491 }
492 
493 // 5.
494 template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
495 void
496 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
497  OutIter out,
498  OFFSETS const& offsets,
499  CONT const& (*extractor)(PROD const*)) const
500 {
501  this->operator()<CONT, CONT const& (*)(PROD const*)>(in,
502  out,
503  offsets,
504  extractor); // 10.
505 }
506 
507 // 6.
508 template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
509 void
510 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
511  OutIter out,
512  OFFSETS const& offsets,
513  CONT const& (PROD::*extractor)() const) const
514 {
515  this->operator()<CONT, CONT const& (PROD::*)() const>(in,
516  out,
517  offsets,
518  extractor); // 10.
519 }
520 
521 // 7.
522 template <typename CONT, typename OutIter, typename PROD, typename OFFSETS>
523 void
524 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
525  OutIter out,
526  OFFSETS const& offsets,
527  CONT const PROD::*data) const
528 {
529  this->operator()<CONT, CONT const PROD::*>(in, out, offsets, data); // 10.
530 }
531 
532 // 8.
533 template <typename PROD,
534  typename OutIter,
535  typename CONT,
536  typename X,
537  typename OFFSETS>
538 void
539 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
540  OutIter out,
541  OFFSETS const& offsets,
542  CONT const& (X::*)(PROD const*),
543  X& x) const
544 {
545  this->operator()<CONT>(
546  in, out, offsets, [&x](auto& elem) { elem.extractor(x); }); // 10.
547 }
548 
549 // 9.
550 template <typename PROD,
551  typename OutIter,
552  typename CONT,
553  typename X,
554  typename OFFSETS>
555 void
556 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
557  OutIter out,
558  OFFSETS const& offsets,
559  CONT const& (X::*)(PROD const*) const,
560  X const& x) const
561 {
562  this->operator()<CONT>(
563  in, out, offsets, [&x](auto& elem) { elem.extractor(x); }); // 10.
564 }
565 
566 // 10.
567 template <typename CONT,
568  typename CALLBACK,
569  typename OutIter,
570  typename PROD,
571  typename OFFSETS>
572 void
573 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
574  OutIter out,
575  OFFSETS const& offsets,
576  CALLBACK extractor) const
577 {
578  if (in.size() != offsets.size()) {
580  << "Collection size of " << in.size()
581  << " disagrees with offset container size of " << offsets.size() << ".\n";
582  }
583  auto i = in.begin();
584  auto const e = in.end();
585  auto off_iter = offsets.begin();
587  for (; i != e; ++i, ++off_iter) {
588  CONT const& cont{returner.operator()(*i)};
589  this->operator()(cont.begin(), cont.end(), out, *off_iter); // 3.
590  }
591 }
592 
593 // --------------------------
594 // art::ProductPtr remappings
595 // --------------------------
596 
597 // 11.
598 template <typename PROD>
601 {
602  if (!oldPtr.id().isValid()) {
603  return {};
604  }
605 
606  auto core = newRefCore_(oldPtr.id());
607  if (core.productGetter()) {
608  return ProductPtr<PROD>{core.id(), core.productGetter()};
609  }
610 
611  throw unknownProduct_<ProductPtr<PROD>>(core.id());
612 }
613 
614 // 12.
615 template <typename PROD>
618  std::vector<ProductPtr<PROD> const*> const& in) const
619 {
620  art::ProductPtr<PROD> result{};
621  for (auto const* ptr : in) {
622  result = samePtrAs(remap(*ptr), result);
623  }
624  return result;
625 }
626 
627 // 13.
628 template <typename PROD, typename T>
630 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
631  ProductPtr<T> const PROD::*data) const
632 {
633  art::ProductPtr<T> result{};
634  for (auto const* ptr : in) {
635  result = samePtrAs(this->operator()(ptr->*data), result);
636  }
637  return result;
638 }
639 
640 // 14.
641 template <typename PROD, typename T>
643 art::PtrRemapper::operator()(std::vector<PROD const*> const& in,
644  ProductPtr<T> const& (PROD::*extractor)()
645  const) const
646 {
647  art::ProductPtr<T> result{};
648  for (auto const* ptr : in) {
649  result = samePtrAs(this->operator()((ptr->*extractor)()), result);
650  }
651  return result;
652 }
653 
654 #endif /* art_Framework_Core_PtrRemapper_h */
655 
656 // Local Variables:
657 // mode: c++
658 // End:
Float_t x
Definition: compare.C:6
static ProductPtr< PROD > samePtrAs(ProductPtr< PROD > result, ProductPtr< PROD > old)
Definition: PtrRemapper.h:391
void reserve(size_type n)
Definition: PtrVector.h:337
iterator begin()
Definition: PtrVector.h:217
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
CONT const & operator()(PROD const *prod) const
Definition: PtrRemapper.h:234
key_type key() const noexcept
Definition: Ptr.h:166
std::map< ProductID, ProductID > ProdTransMap_t
Definition: PtrRemapper.h:385
iterator end()
Definition: PtrVector.h:231
PROD const & simpleProdReturner(PROD const *prod)
Definition: PtrRemapper.h:223
bool isNull() const noexcept
Definition: Ptr.h:211
ProductID id() const noexcept
Definition: Ptr.h:160
size_type size() const
Definition: PtrVector.h:302
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
ifstream in
Definition: comparison.C:7
static auto unknownProduct_(ProductID const id)
Definition: PtrRemapper.h:405
Definition: MVAAlg.h:12
ProductID id() const noexcept
Definition: ProductPtr.h:124
Ptr< PROD > operator()(Ptr< PROD > const &oldPtr, SIZE_TYPE offset) const
Float_t e
Definition: plot.C:35
Float_t X
Definition: plot.C:37
Definition: fwd.h:26