MappedContainer.h
Go to the documentation of this file.
1 /**
2  * @file lardataalg/Utilities/MappedContainer.h
3  * @brief Provides `MappedContainer` class.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date March 22, 2019
6  *
7  * This is a header-only library.
8  */
9 
10 #ifndef LARDATAALG_UTILITIES_MAPPEDCONTAINER_H
11 #define LARDATAALG_UTILITIES_MAPPEDCONTAINER_H
12 
13 // LArSoft libraries
14 #include "larcorealg/CoreUtils/ContainerMeta.h" // util::collection_value_access_t
15 #include "larcorealg/CoreUtils/MetaUtils.h" // util::with_const_as_t
16 
17 // C/C++ standard libraries
18 #include <string> // std::to_string()
19 #include <iterator> // std::iterator_category, std::size(), ...
20 #include <memory> // std::unique_ptr<>
21 #include <algorithm> // std::reference_wrapper<>
22 #include <stdexcept> // std::out_of_range
23 #include <limits> // std::numeric_limits<>
24 #include <cstddef> // std::size_t
25 
26 
27 namespace util {
28 
29  namespace details {
30 
31  // ---------------------------------------------------------------------------
32  template <typename Cont> struct ContainerTraits;
33 
34  // ---------------------------------------------------------------------------
35  template <typename Cont, typename = void> class ContainerStorage;
36 
37  // ---------------------------------------------------------------------------
38 
39  } // namespace details
40 
41  // ---------------------------------------------------------------------------
42  /// Non-template base class for `MappedContainer`.
44 
45  template <typename T = std::size_t>
46  static constexpr T invalidIndex() { return std::numeric_limits<T>::max(); }
47 
48  }; // struct MappedContainerBase
49 
50 
51  // ---------------------------------------------------------------------------
52  /**
53  * @brief A meta-container providing transparent mapping on top of another.
54  * @tparam Cont type of the underlying container
55  * @tparam Mapping type of the mapping to be applied
56  *
57  *
58  * The mapped data is not permanently stored in memory, but rather the mapping
59  * is applied anew on each request. If a permanent mapped container is
60  * desired, a copy of this container into a standard one (e.g. a
61  * `std::vector`) can be used.
62  *
63  * Note that the data itself is not modified by this container (although it
64  * may be just a copy of the original one: see note about storage below).
65  *
66  * Example of usage:
67  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
68  * constexpr auto InvalidIndex = util::MappedContainerBase::invalidIndex();
69  *
70  * std::array<double, 4U> const data { 0.0, -1.0, -2.0, -3.0 };
71  *
72  * std::array<std::size_t, 6U> const mapping = {
73  * 1U, 0U, InvalidIndex,
74  * 3U, 2U, InvalidIndex,
75  * };
76  *
77  * util::MappedContainer const mappedData
78  * (std::ref(data), mapping, 6U, std::numeric_limits<double>::quiet_NaN());
79  *
80  * for (std::size_t i = 0; i < 6U; ++i) {
81  * std::cout
82  * << "Mapped element #" << i << ": " << mappedData[i] << std::endl;
83  * }
84  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85  * which will print a list similar to: `-1.0`, `0.0`, `nan`, `-3.0`, `-2.0`
86  * and `nan`.
87  * Note that wrapping the original data into `std::ref` ensures that data is
88  * referenced rather than copied, while (in this example) the mapping is
89  * instead just copied. Wrapping it in `std::cref` would ensure the access to
90  * be in the `const` fashion even if the data array were not constant.
91  * The argument `6U` ensures that the container can address 6 indices.
92  * In this example, it is needed only because then we specify a default value;
93  * `MappedContainer` is otherwise able to use as size the size of the mapping,
94  * if the mapping has one
95  * (see `MappedContainer(DataContainer_t const&, Mapping_t const&)`).
96  * Also note that in the example the C++17 template argument deduction is used
97  * and it's not necessary to specify those argument explicitly (it would be
98  * `util::MappedContainer<std::array<double, 4U> const, std::array<std::size_t, 6U> const>`).
99  *
100  *
101  * Storage and ownership of the mapped data
102  * -----------------------------------------
103  *
104  * If `Cont` is a C++ reference type, a C pointer, or a
105  * `std::reference_wrapper` object, the original container is referenced.
106  * Otherwise, a copy of it is internally stored with all data duplicated
107  * according to the container copy constructor.
108  *
109  *
110  * C++ standard
111  * -------------
112  *
113  * This object fulfills most of the "Container" requirements, except for:
114  * * container comparisons: they can be implemented if needed, but they would
115  * be slow
116  * * `swap()`: did nor really bother to...
117  *
118  * It also fulfills most of the "SequentialContainer" requirements that are
119  * not about construction or modification of the container size.
120  *
121  */
122  template <typename Cont, typename Mapping>
124 
125  /// Type of object used for storage.
127 
128  /// Type of object used for mapping storage.
130 
131  /// Type of contained value.
132  using Value_t = typename Storage_t::value_type;
133 
134  using Size_t = std::size_t; ///< Type for describing container size.
135 
136  Storage_t fData; ///< Data to be mapped.
137 
138  MappingStorage_t fMapping; ///< Mapping of stored data into final one.
139 
140  Size_t fSize = 0U; ///< Nominal size of the container.
141 
142  // constantness needs to be removed in order for this object to be copiable
143  ///< Value returned for elements not mapped.
144  std::remove_cv_t<Value_t> fDefValue {};
145 
146 
147  template <typename Container, typename Reference>
149 
150 
151  public:
152 
153  using DataContainer_t = Cont; ///< Type of the original container.
154  using Mapping_t = Mapping; ///< Type of the mapping object.
155 
156  /// Type of this class.
158 
159  /// Type of the index passed to the original container.
161 
162  /// Type of the index passed to the mapping.
163  using MappingIndex_t = std::size_t;
164 
165 
166  // --- BEGIN -- C++ standard container definitions -------------------------
167  /// @name C++ standard container definitions
168  /// @{
169  /// Type of datum in the container.
171 
172  using size_type = std::size_t;
173  using difference_type = std::ptrdiff_t;
174 
176  typename Storage_t::reference,
178  >;
180 
181  using iterator = IteratorBase<MappedContainer_t, reference>;
182  using const_iterator
183  = IteratorBase<MappedContainer_t const, const_reference>;
184 
185  /// @}
186  // --- END -- C++ standard container definitions ---------------------------
187 
188 
189  /// Invalid index to be returned by the mapping when the required index is
190  /// not mapped back to the original container; in that case, a
191  /// `defaultValue()` is mapped instead.
192  static constexpr DataIndex_t InvalidIndex = invalidIndex<DataIndex_t>();
193 
194 
195  // --- BEGIN Constructors --------------------------------------------------
196  /// @name Constructors
197  /// @{
198 
199  /// Default constructor: container will be unusable until assigned to.
200  MappedContainer() = default;
201 
202  /**
203  * @brief Constructor: acquires data, mapping and a default value.
204  * @param cont container with the data to be mapped
205  * @param mapping the mapping to be used
206  * @param size the size of the container after mapping
207  * @param defValue value to be used as default
208  *
209  * The `defValue` value is returned for the requested elements which are not
210  * mapped to the original container (`InvalidIndex`).
211  */
213  DataContainer_t const& cont,
214  Mapping_t const& mapping,
215  size_type size,
216  value_type defValue
217  )
218  : fData(cont), fMapping(mapping), fSize(size), fDefValue(defValue)
219  {}
220 
221  /**
222  * @brief Constructor: acquires data and mapping.
223  * @param cont container with the data to be mapped
224  * @param mapping the mapping to be used
225  * @param size the size of the container after mapping
226  *
227  * The default value is a default-constructed `value_type` (`0` for numeric
228  * types, `nullptr` for pointers).
229  */
231  (DataContainer_t const& cont, Mapping_t const& mapping, size_type size)
232  : MappedContainer(cont, mapping, size, {})
233  {}
234 
235  /**
236  * @brief Constructor: acquires data and mapping.
237  * @param cont container with the data to be mapped
238  * @param mapping the mapping to be used
239  *
240  * The size of the container is declared to be the minimal one
241  * (see `minimal_size()`).
242  * The default value is a default-constructed `value_type` (`0` for numeric
243  * types, `nullptr` for pointers).
244  */
245  MappedContainer(DataContainer_t const& cont, Mapping_t const& mapping)
246  : MappedContainer(cont, mapping, minimal_size(cont, mapping))
247  {}
248 
249  /// @}
250  // --- END Constructors ----------------------------------------------------
251 
252 
253  // --- BEGIN Container information -----------------------------------------
254  /**
255  * @name Container information
256  *
257  * The size of the container after mapping is not strictly defined, since
258  * there might be elements not present in the original container, as well
259  * as those elements might appear more than once.
260  *
261  * On top of this, this object does not need to know the size to correctly
262  * operate, because no storage is used for the container data after mapping.
263  *
264  * Nevertheless, users may rightfully wonder and ask how many elements of
265  * the container are valid after the mapping.
266  *
267  * This class allows an answer to be provided at construction time, relying
268  * on the superior wisdom of the user. If the user does not care to impart
269  * such wisdom, a guess is made with using the minimal size needed to
270  * accommodate all the elements after mapping (see `minimal_size()`).
271  */
272  /// @{
273 
274  /**
275  * @brief Returns the nominal size of the container (after mapping).
276  *
277  * This is the value provided at construction time, or the `minimal_size()`
278  * at that time if no value was provided.
279  */
280  size_type size() const { return fSize; }
281 
282  /**
283  * @brief Returns the minimum size to include all mapped values.
284  *
285  * This method is available only if the mapping type (`Mapping_t`) answers
286  * a `std::size()` call, which is expected to return the number of elements
287  * the original data can be mapped into.
288  */
289  size_type minimal_size() const;
290 
291  /// Returns the size of the largest possible container of this type.
293 
294  /// Returns whether the container has no elements.
295  bool empty() const { return size() == 0U; }
296 
297 
298  // @{
299  /**
300  * @brief Returns the default value for elements with no original content.
301  *
302  * Note that changing it will change at the same time the value returned
303  * for all unmapped elements afterwards.
304  */
305  reference defaultValue() { return fDefValue; }
306  const_reference defaultValue() const { return fDefValue; }
307  // @}
308 
309 
310  /// Changes the default value.
311  /// The new value will be used for all following mappings.
312  void setDefaultValue(value_type defValue) { fDefValue = defValue; }
313 
314 
315  /// @}
316  // --- END Container information -------------------------------------------
317 
318 
319  // --- BEGIN Random access to elements -------------------------------------
320  /// @name Random access to elements
321  /// @{
322 
323  // @{
324  /**
325  * @brief Returns the content corresponding to the specified `index`.
326  * @param index the index of the data to be retrieved
327  * @return the mapped value (some decoration of `value_type`)
328  *
329  * The content requested for `index` is fetched from the original data, at
330  * the element resulting from the mapping of the `index` argument.
331  */
332  decltype(auto) operator[] (MappingIndex_t index) const
333  { return map_element(index); }
334  decltype(auto) operator[] (MappingIndex_t index)
335  { return map_element(index); }
336  // @}
337 
338  // @{
339  /**
340  * @brief Returns the content corresponding to the specified `index`.
341  * @param index the index of the data to be retrieved
342  * @return the mapped value (some decoration of `value_type`)
343  * @throw std::out_of_range if the index is not in the container
344  */
345  decltype(auto) at(MappingIndex_t index) const;
346  decltype(auto) at(MappingIndex_t index);
347  // @}
348 
349 
350  // @{
351  /**
352  * @brief Returns the first element in the container.
353  * @return the first element in the container, undefined if `empty()`
354  */
355  decltype(auto) front() const { return map_element(0U); }
356  decltype(auto) front() { return map_element(0U); }
357  // @}
358 
359  // @{
360  /**
361  * @brief Returns the last element in the container.
362  * @return the last element in the container, undefined if `empty()`
363  */
364  decltype(auto) back() const { return map_element(size() - 1); }
365  decltype(auto) back() { return map_element(size() - 1); }
366  // @}
367 
368 
369  // @{
370  /**
371  * @brief Returns the index in the original data which is mapped to `index`.
372  * @param index the index to be mapped (like e.g. in `at()`)
373  * @return the index in the original data container, or `InvalidIndex`
374  */
375  decltype(auto) map_index(MappingIndex_t index) const;
376  decltype(auto) map_index(MappingIndex_t index);
377  // @}
378 
379 
380  /// @}
381  // --- END Random access to elements ---------------------------------------
382 
383 
384  // --- BEGIN Iteration -----------------------------------------------------
385  /// @name Iteration
386  /// @{
387 
388  /// Returns a constant iterator to the first mapped element.
389  const_iterator cbegin() const { return { *this, 0U }; }
390 
391  /// Returns a constant iterator to the first mapped element.
392  const_iterator begin() const { return cbegin(); }
393 
394  /// Returns an iterator to the first mapped element.
395  iterator begin() { return { *this, 0U }; }
396 
397  /// Returns a constant iterator past the last mapped element.
398  const_iterator cend() const { return { *this, size() }; }
399 
400  /// Returns a constant iterator past the last mapped element.
401  const_iterator end() const { return cend(); }
402 
403  /// Returns an iterator past the last mapped element.
404  iterator end() { return { *this, size() }; }
405 
406  /// @}
407  // --- END Iteration -------------------------------------------------------
408 
409  protected:
410 
411  /// Returns the minimum size to include all mapped values.
412  static size_type minimal_size
413  (DataContainer_t const& cont, Mapping_t const& mapping);
414 
415 
416  private:
417 
418  /// Returns the value mapped to the specified `index`.
419  decltype(auto) map_element(MappingIndex_t index);
420 
421  /// Returns the value mapped to the specified `index`.
422  decltype(auto) map_element(MappingIndex_t index) const;
423 
424 
425  }; // class MappedContainer<>
426 
427 
428  //----------------------------------------------------------------------------
429  /**
430  * @brief Returns a container-like object mapping the content of `cont`.
431  * @tparam Cont type of the original container
432  * @tparam Mapping type of mapping object
433  * @param cont the container
434  * @param mapping the mapping to be applied
435  * @return a `util::MappedContainer` object transparently applying the mapping
436  *
437  * See `util::MappedContainer` for the details on the format of the mapping,
438  * the ownership of the container and the supported operations.
439  */
440  template <typename Cont, typename Mapping>
441  auto mapContainer(Cont cont, Mapping mapping)
442  { return MappedContainer<Cont, Mapping>(cont, mapping); }
443 
444 
445  //----------------------------------------------------------------------------
446 
447 
448 } // namespace util
449 
450 
451 //------------------------------------------------------------------------------
452 //--- template implementation
453 //------------------------------------------------------------------------------
454 namespace util {
455 
456  namespace details {
457 
458  //--------------------------------------------------------------------------
459  template <typename T>
460  T& NullRef() { T* nullTptr = nullptr; return *nullTptr; }
461 
462 
463  //--------------------------------------------------------------------------
464  //--- ContainerStorage
465  //--------------------------------------------------------------------------
466  template <typename Cont>
468 
469  using Container_t = Cont;
471 
472  using index_type = typename Traits_t::size_type;
473 
475  using size_type = typename Traits_t::size_type;
477  using reference = typename Traits_t::reference;
479 
481 
482  ContainerStorageBase() = default;
483  explicit ContainerStorageBase(Container_t const& cont): fCont(cont) {}
485  : fCont(std::move(cont)) {}
486 
487  decltype(auto) container() const
488  { return util::collection_from_reference(fCont); }
489  decltype(auto) container()
490  { return util::collection_from_reference(fCont); }
491 
492  auto size() const { using std::size; return size(container()); }
493 
494  decltype(auto) operator[] (index_type index)
495  { return container()[index]; }
496  decltype(auto) operator[] (index_type index) const
497  { return container()[index]; }
498 
499  }; // struct ContainerStorageBase
500 
501 
502  //--------------------------------------------------------------------------
503  template <typename Cont, typename /* = void */>
504  class ContainerStorage: public ContainerStorageBase<Cont> {
505 
507 
508  // inherit all constructors
509  using Base_t::Base_t;
510 
511  }; // struct ContainerStorage
512 
513 
514  template <typename Cont>
516  <Cont, std::enable_if_t<util::is_reference_wrapper_v<Cont>>>
517  : public ContainerStorageBase<Cont>
518  {
520  using DataContainer_t = typename Cont::type;
521 
522  public:
523  // inherit all constructors
524  using Base_t::Base_t;
525 
526  // sad hack :-(
527  // calling the inherited constructor with a `reference_wrapper`
528  // (`Base_t::Container_t`) referencing an invalid reference to
529  // the wrapped data type (which is `DataContainer_t`).
531  : Base_t(typename Base_t::Container_t{NullRef<DataContainer_t>()})
532  {}
533 
534  }; // struct ContainerStorage
535 
536 
537  //--------------------------------------------------------------------------
538 
539 
540  } // namespace details
541 
542 
543  //----------------------------------------------------------------------------
544  //--- MappedContainer::IteratorBase
545  //----------------------------------------------------------------------------
546  template <typename Cont, typename Mapping>
547  template <typename Container, typename Reference>
548  class MappedContainer<Cont, Mapping>::IteratorBase {
549 
550  using Container_t = Container;
551  using Reference_t = Reference;
552 
553  /// This type.
555 
556  Container_t* fCont = nullptr; ///< Pointer to the container.
557  MappingIndex_t fIndex = InvalidIndex; ///< Current index in container.
558 
559  public:
560 
561  // --- BEGIN Traits --------------------------------------------------------
562  /// @name Traits
563  /// @{
564 
565  using value_type = std::remove_cv_t<typename Container_t::value_type>;
566  using difference_type = typename Container_t::difference_type;
567  using size_type = typename Container_t::size_type;
569  using pointer = decltype(&std::declval<reference>());
570  using iterator_category = std::input_iterator_tag;
571 
572  /// @}
573  // --- END Traits ----------------------------------------------------------
574 
575 
576  /// Constructor: an invalid iterator.
577  IteratorBase() = default;
578 
579  /// Constructor: iterator pointing to element `index` of `cont`.
581  : fCont(&cont), fIndex(index)
582  {}
583 
584  /// Copy constructor.
585  IteratorBase(Iterator_t const&) = default;
586 
587  /// Copy constructor: from a different container type.
588  template <typename OC, typename OR>
590  : fCont(from.cont), fIndex(from.index)
591  {}
592 
593  /// Copy assignment.
594  Iterator_t& operator= (Iterator_t const&) = default;
595 
596  /// Assignment from a different container type.
597  template <typename OC, typename OR>
598  Iterator_t& operator= (IteratorBase<OC, OR> const& from)
599  { fCont = from.fCont; fIndex = from.fIndex; return *this; }
600 
601 
602  // --- BEGIN Dereferencing -------------------------------------------------
603  /// @name Dereferencing
604  /// @{
605  /// Returns the mapped item the iterator currently points to.
606  reference operator*() const { return (*fCont)[fIndex]; }
607 
608  /// Returns a member of the mapped item the iterator currently points to.
609  reference operator->() const { return &(operator*(fIndex)); }
610 
611  /// Returns the mapped item `n` steps ahead of what the iterator currentlt
612  /// points to.
613  reference operator[] (difference_type n) const
614  { return (*fCont)[fIndex + n]; }
615 
616  /// @}
617  // --- END Dereferencing ---------------------------------------------------
618 
619 
620  // --- BEGIN Transformation ------------------------------------------------
621  /// @name Transformation
622  /// @{
623  /// Increments this iterator and returns it incremented.
624  Iterator_t& operator++() { ++fIndex; return *this; }
625 
626  /// Increments this iterator and returns its old value.
627  Iterator_t operator++(int) { auto it = *this; this->operator++(); return it; }
628 
629  /// Decrements this iterator and returns it decremented.
630  Iterator_t& operator--() { --fIndex; return *this; }
631 
632  /// Decrements this iterator and returns its old value.
633  Iterator_t operator--(int) { auto it = *this; this->operator--(); return it; }
634 
635  /// Increments this iterator by `n` steps and returns it incremented.
636  Iterator_t& operator+= (difference_type n) { fIndex += n; return *this; }
637 
638  /// Decrements this iterator by `n` steps and returns it decremented.
639  Iterator_t& operator-= (difference_type n) { fIndex -= n; return *this; }
640 
641  /// Returns an iterator pointing `n` steps ahead of this one.
643  { auto it = *this; it += n; return it; }
644 
645  /// Returns an iterator pointing `n` steps behind this one.
647  { auto it = *this; it -= n; return it; }
648 
649  /// Returns the number of steps this iterator is ahead of `other`.
651  { return fIndex - other.fIndex; }
652 
653  /// @}
654  // --- END Transformation --------------------------------------------------
655 
656 
657  // --- BEGIN Comparisons ---------------------------------------------------
658  /// @name Comparisons
659  /// @{
660  /// Returns whether this iterator is equal to `other`.
661  template <typename OC, typename OR>
663  { return (fCont == other.fCont) && (fIndex == other.fIndex); }
664 
665  /// Returns whether this iterator is not equal to `other`.
666  template <typename OC, typename OR>
668  { return (fCont != other.fCont) || (fIndex != other.fIndex); }
669 
670  /// Returns whether this iterator is behind of or equal to `other`.
671  template <typename OC, typename OR>
672  bool operator<= (IteratorBase<OC, OR> const& other) const
673  { return (fCont == other.fCont) && (fIndex <= other.fIndex); }
674 
675  /// Returns whether this iterator is strictly behind of `other`.
676  template <typename OC, typename OR>
677  bool operator< (IteratorBase<OC, OR> const& other) const
678  { return (fCont == other.fCont) && (fIndex < other.fIndex); }
679 
680  /// Returns whether this iterator is ahead of or equal to `other`.
681  template <typename OC, typename OR>
683  { return (fCont == other.fCont) && (fIndex >= other.fIndex); }
684 
685  /// Returns whether this iterator is strictly ahead of `other`.
686  template <typename OC, typename OR>
688  { return (fCont == other.fCont) && (fIndex > other.fIndex); }
689 
690  /// @}
691  // --- END Comparisons -----------------------------------------------------
692 
693  }; // IteratorBase
694 
695 
696  // it hurts the eye
697  template <
698  typename Cont, typename Mapping,
699  typename Container, typename Reference
700  >
702  operator+
703  (
704  typename MappedContainer<Cont, Mapping>::template IteratorBase<Container, Reference>::difference_type n,
705  typename MappedContainer<Cont, Mapping>::template IteratorBase<Container, Reference> const& it
706  )
707  { return it + n; }
708 
709 
710 } // namespace util
711 
712 
713 
714 namespace util::details {
715 
716 
717  //----------------------------------------------------------------------------
718  template <typename Cont>
720  using value_type = typename Cont::value_type;
721  using difference_type = typename Cont::difference_type;
722  using size_type = typename Cont::size_type;
723  using const_reference = typename Cont::const_reference;
724  using reference = typename Cont::reference;
726  using iterator = typename Cont::iterator;
727  }; // ContainerTraitsImpl<>
728 
729  template <typename T>
731  using value_type = T; // should it be devoid of const/mutable?
732  using difference_type = std::ptrdiff_t;
733  using size_type = std::size_t;
734  using const_reference = T const&;
735  using reference = T&;
736  using const_iterator = T const*;
737  using iterator = T*;
738  }; // ContainerTraitsImpl<T*>
739 
740  // this is not as powerful as it should... hoping users do not nest
741  // crazily `unique_ptr`, `reference_wrapper` and such
742  template <typename Cont>
743  struct ContainerTraits
745  std::remove_reference_t<
746  util::collection_from_reference_t<
747  util::strip_referenceness_t<Cont>
748  >
749  >
750  >
751  {};
752 
753 
754  //----------------------------------------------------------------------------
755 
756 } // namespace util::details
757 
758 
759 //------------------------------------------------------------------------------
760 //--- util::MappedContainer
761 //------------------------------------------------------------------------------
762 template <typename Cont, typename Mapping>
764  { return minimal_size(fData.container(), fMapping.container()); }
765 
766 
767 //------------------------------------------------------------------------------
768 template <typename Cont, typename Mapping>
770  (MappingIndex_t index) const
771 {
772  auto const dataIndex = map_index(index);
773  return (dataIndex == InvalidIndex)? defaultValue(): fData[dataIndex];
774 } // util::MappedContainer<>::map_element() const
775 
776 
777 //------------------------------------------------------------------------------
778 template <typename Cont, typename Mapping>
780  (MappingIndex_t index)
781 {
782  auto const dataIndex = map_index(index);
783  return (dataIndex == InvalidIndex)? defaultValue(): fData[dataIndex];
784 } // util::MappedContainer<>::map_element()
785 
786 
787 //------------------------------------------------------------------------------
788 template <typename Cont, typename Mapping>
790  (MappingIndex_t index) const
791 {
792  if (index >= size()) {
793  throw std::out_of_range(
794  "MappedContainer::at(" + std::to_string(index) + "): out of range (size: "
795  + std::to_string(size()) + ")"
796  );
797  }
798  return map_element(index);
799 } // util::MappedContainer<>::at() const
800 
801 
802 //------------------------------------------------------------------------------
803 template <typename Cont, typename Mapping>
805  (MappingIndex_t index)
806 {
807  if (index >= size()) {
808  throw std::out_of_range(
809  "MappedContainer::at(" + std::to_string(index) + "): out of range (size: "
810  + std::to_string(size()) + ")"
811  );
812  }
813  return map_element(index);
814 } // util::MappedContainer<>::at()
815 
816 
817 //------------------------------------------------------------------------------
818 template <typename Cont, typename Mapping>
820  (DataContainer_t const&, Mapping_t const& mapping) -> size_type
821 {
822  /*
823  * Obscure compiler errors are expected if the `Mapping_t` type does not
824  * support `std::size`. In that case, very simply, `minimal_size()` can't be
825  * used and the caller must specify the size of the container.
826  */
827 
828  using std::size;
829  return size(util::collection_from_reference(mapping));
830 } // util::MappedContainer<>::minimal_size(DataContainer_t, Mapping_t)
831 
832 
833 //------------------------------------------------------------------------------
834 template <typename Cont, typename Mapping>
836  (MappingIndex_t index) const
837  { return fMapping[index]; }
838 
839 
840 //------------------------------------------------------------------------------
841 template <typename Cont, typename Mapping>
843  (MappingIndex_t index)
844  { return fMapping[index]; }
845 
846 
847 //------------------------------------------------------------------------------
848 
849 
850 #endif // LARDATAALG_UTILITIES_MAPPEDCONTAINER_H
MappedContainer< Cont, Mapping >::template IteratorBase< Container, Reference > operator+(typename MappedContainer< Cont, Mapping >::template IteratorBase< Container, Reference >::difference_type n, typename MappedContainer< Cont, Mapping >::template IteratorBase< Container, Reference > const &it)
intermediate_table::iterator iterator
auto mapContainer(Cont cont, Mapping mapping)
Returns a container-like object mapping the content of cont.
typename collection_value_access_type< Coll >::type collection_value_access_t
Type obtained by constant access to element of collection Coll.
Definition: ContainerMeta.h:76
Namespace for general, non-LArSoft-specific utilities.
typename Storage_t::value_type Value_t
Type of contained value.
IteratorBase(IteratorBase< OC, OR > const &from)
Copy constructor: from a different container type.
MappingIndex_t fIndex
Current index in container.
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::iterator iterator
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Definition: StdUtils.h:87
A meta-container providing transparent mapping on top of another.
Basic C++ metaprogramming utilities.
DoubleProduct & operator+=(DoubleProduct &left, DoubleProduct const &right)
Definition: ToyProducts.h:103
Iterator_t & operator--()
Decrements this iterator and returns it decremented.
const_reference defaultValue() const
size_type minimal_size() const
Returns the minimum size to include all mapped values.
std::size_t MappingIndex_t
Type of the index passed to the mapping.
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::size_type size_type
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::reference reference
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::const_reference const_reference
ContainerStorageBase(Container_t const &cont)
const_iterator cbegin() const
Returns a constant iterator to the first mapped element.
STL namespace.
typename with_const_as< Base, Key >::type with_const_as_t
The type Base, plus the constantness as in Key.
Definition: MetaUtils.h:549
size_type size() const
Returns the nominal size of the container (after mapping).
std::remove_cv_t< typename Container_t::value_type > value_type
intermediate_table::const_iterator const_iterator
Iterator_t operator++(int)
Increments this iterator and returns its old value.
Iterator_t operator--(int)
Decrements this iterator and returns its old value.
const_iterator begin() const
Returns a constant iterator to the first mapped element.
static constexpr T invalidIndex()
Non-template base class for MappedContainer.
util::with_const_as_t< typename Storage_t::reference, util::collection_value_access_t< DataContainer_t > > reference
typename Container_t::size_type size_type
void setDefaultValue(value_type defValue)
IteratorBase(Container_t &cont, MappingIndex_t index)
Constructor: iterator pointing to element index of cont.
QuadExpr operator-(double v, const QuadExpr &e)
Definition: QuadExpr.h:38
ContainerStorageBase(Container_t &&cont)
const Index InvalidIndex
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
iterator end()
Returns an iterator past the last mapped element.
std::void_t< T > n
decltype(auto) map_index(MappingIndex_t index) const
Returns the index in the original data which is mapped to index.
def move(depos, offset)
Definition: depos.py:107
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::difference_type difference_type
typename Container_t::difference_type difference_type
phot::IPhotonLibrary::T0s_t DataContainer_t
Type of the original container.
const_iterator cend() const
Returns a constant iterator past the last mapped element.
static int max(int a, int b)
decltype(auto) map_element(MappingIndex_t index)
Returns the value mapped to the specified index.
decltype(&std::declval< reference >()) pointer
IteratorBase< MappedContainer_t const, const_reference > const_iterator
iterator begin()
Returns an iterator to the first mapped element.
decltype(auto) container() const
MappingStorage_t fMapping
Mapping of stored data into final one.
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::value_type value_type
MappedContainer(DataContainer_t const &cont, Mapping_t const &mapping)
Constructor: acquires data and mapping.
const_iterator end() const
Returns a constant iterator past the last mapped element.
typename std::remove_reference_t< util::collection_from_reference_t< util::strip_referenceness_t< Cont > > >::const_iterator const_iterator
std::vector< size_t > Mapping(std::vector< geo::AuxDetGeo * > &adgeo)
util::collection_value_t< Mapping_t > DataIndex_t
Type of the index passed to the original container.
size_type max_size() const
Returns the size of the largest possible container of this type.
static QCString type
Definition: declinfo.cpp:672
Container_t * fCont
Pointer to the container.
bool empty() const
Returns whether the container has no elements.
std::input_iterator_tag iterator_category
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:82
bool operator!=(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Never admit a infinite_endcount_iterator to be equal to anything else.
Definition: counter.h:259
Storage_t fData
Data to be mapped.
decltype(auto) at(MappingIndex_t index) const
Returns the content corresponding to the specified index.
reference defaultValue()
Returns the default value for elements with no original content.
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:65
MappedContainer(DataContainer_t const &cont, Mapping_t const &mapping, size_type size, value_type defValue)
Constructor: acquires data, mapping and a default value.
bool operator>(const VectorMap< _Key, _Tp, _Compare > &__x, const VectorMap< _Key, _Tp, _Compare > &__y)
Based on operator<.
Definition: VectorMap.h:521
decltype(auto) collection_from_reference(CollRef &collRef)
Returns the object referenced by collRef as a C++ reference.
C++ metaprogramming utilities for dealing with containers.
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Definition: counter.h:269
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
reference operator->() const
Returns a member of the mapped item the iterator currently points to.
bool operator>=(const VectorMap< _Key, _Tp, _Compare > &__x, const VectorMap< _Key, _Tp, _Compare > &__y)
Based on operator<.
Definition: VectorMap.h:537
typename Traits_t::difference_type difference_type
std::size_t Size_t
Type for describing container size.