LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
CollectionProxy.h
Go to the documentation of this file.
1 
11 #ifndef LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXY_H
12 #define LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXY_H
13 
14 // LArSoft libraries
15 #include "larcorealg/CoreUtils/ContainerMeta.h" // util::collection_value_t, ...
18 #include "lardata/Utilities/TupleLookupByTag.h" // util::type_with_tag_t, ...
19 
20 // C/C++ standard
21 #include <cstdlib> // std::size_t
22 #include <limits> // std::numeric_limits<>
23 #include <tuple>
24 #include <utility> // std::move()
25 #include <vector>
26 
27 namespace proxy {
28 
29  namespace details {
30 
31  template <typename Cont>
33 
34  template <template <typename, typename...> class F, typename...>
36 
37  } // namespace details
38 
39  // --- BEGIN Collection proxy infrastructure ---------------------------------
76  //----------------------------------------------------------------------------
109  template <template <typename CollProxy> class Element, typename MainColl, typename... AuxColls>
110  class CollectionProxyBase : public details::MainCollectionProxy<MainColl>, public AuxColls... {
112  using collection_proxy_t = CollectionProxyBase<Element, MainColl, AuxColls...>;
113 
116 
117  public:
120 
123 
125  using element_proxy_t = Element<collection_proxy_t>;
126 
128  using aux_collections_t = std::tuple<AuxColls...>;
129 
132 
135 
138 
148  CollectionProxyBase(main_collection_t const& main, AuxColls&&... aux)
149  : main_collection_proxy_t(main), AuxColls(std::move(aux))...
150  {}
151 
162  element_proxy_t const operator[](std::size_t i) const
163  {
164  return details::makeCollectionProxyElement<element_proxy_t>(
165  i, getMainAt(i), aux<AuxColls>().operator[](i)...);
166  }
167 
169  const_iterator begin() const { return makeIterator(0U); }
170 
172  const_iterator end() const { return makeIterator(size()); }
173 
175  bool empty() const { return main().empty(); }
176 
178  std::size_t size() const { return main().size(); }
179 
181  template <typename AuxTag>
182  auto get() const -> decltype(auto)
183  {
184  return auxByTag<AuxTag>();
185  }
186 
240  template <typename Tag, typename T = std::vector<Tag> const&>
241  [[deprecated("Use C++17 constexpr if instead and get() instead")]] auto getIf() const
242  -> decltype(auto);
243 
245  template <typename Tag>
246  static constexpr bool has()
247  {
248  return util::has_tag_v<Tag, aux_collections_t>;
249  }
250 
251  protected:
252  using main_collection_proxy_t::getMainAt;
254  using main_collection_proxy_t::mainProxy;
255 
257  template <typename AuxColl>
258  AuxColl const& aux() const
259  {
260  return static_cast<AuxColl const&>(*this);
261  }
262 
264  template <typename AuxTag>
265  auto auxByTag() const -> decltype(auto)
266  {
267  return aux<util::type_with_tag_t<AuxTag, aux_collections_t>>();
268  }
269 
270  template <typename Tag, typename>
271  auto getIfHas(std::bool_constant<true>) const -> decltype(auto);
272  template <typename Tag, typename T>
273  [[noreturn]] auto getIfHas(std::bool_constant<false>) const -> T;
274 
276  const_iterator makeIterator(std::size_t i) const { return {*this, i}; }
277 
279  "Some auxiliary data collections share the same tag. They should not.");
280 
281  }; // struct CollectionProxyBase
282 
283  //----------------------------------------------------------------------------
293  template <typename MainColl, typename... AuxColls>
295 
296  // this joke is necessary because expanding directly CollectionProxy<Args...>
297  // into CollectionProxy<Main, Aux...> template arguments does not work
298  template <typename... Args>
301 
303  // --- END Collection proxy infrastructure -----------------------------------
304 
305  //----------------------------------------------------------------------------
306  namespace details {
307 
308  //--------------------------------------------------------------------------
310  template <template <typename...> class CollProxy, typename MainColl, typename... AuxColl>
311  auto createCollectionProxy(MainColl const& main, AuxColl&&... aux)
312  {
313  return CollProxy<MainColl, AuxColl...>(main, std::forward<AuxColl>(aux)...);
314  }
315 
316  //--------------------------------------------------------------------------
318  template <typename MainColl, typename... AuxColl>
319  auto makeCollectionProxy(MainColl const& main, AuxColl&&... aux)
320  {
321  return createCollectionProxy<CollectionProxy>(main, std::forward<AuxColl>(aux)...);
322  }
323 
324  //--------------------------------------------------------------------------
331  template <typename Cont>
332  class IndexBasedIterator {
333 
334  public:
335  using container_t = Cont;
336 
339 
341  IndexBasedIterator() = default;
342 
344  IndexBasedIterator(container_t const& cont, std::size_t index = 0)
345  : fCont(&cont), fIndex(index)
346  {}
347 
349  auto operator*() const -> decltype(auto) { return fCont->operator[](fIndex); }
350 
353  {
354  ++fIndex;
355  return *this;
356  }
357 
359  bool operator!=(const_iterator const& other) const
360  {
361  return (other.fIndex != fIndex) || (other.fCont != fCont);
362  }
363 
364  protected:
365  container_t const* fCont = nullptr;
366 
368  std::size_t fIndex = std::numeric_limits<std::size_t>::max();
369 
370  }; // IndexBasedIterator<>
371 
372  } // namespace details
373 
374 } // namespace proxy
375 
376 //------------------------------------------------------------------------------
377 //--- template implementation
378 //------------------------------------------------------------------------------
379 namespace proxy {
380 
381  namespace details {
382 
383  //--------------------------------------------------------------------------
384  template <template <typename, typename...> class F, typename First, typename... Others>
385  struct TemplateAdaptorOnePlus<F, First, Others...> {
386  using type = F<First, Others...>;
387  };
388 
389  } // namespace details
390 
391  //----------------------------------------------------------------------------
392  //--- CollectionProxyBase
393  //----------------------------------------------------------------------------
394  template <template <typename CollProxy> class Element, typename MainColl, typename... AuxColls>
395  template <typename Tag, typename T>
397  {
398  return getIfHas<Tag, T>(std::bool_constant<has<Tag>()>{});
399  }
400 
401  template <template <typename CollProxy> class Element, typename MainColl, typename... AuxColls>
402  template <typename Tag, typename>
404  -> decltype(auto)
405  {
406  return get<Tag>();
407  }
408 
409  template <template <typename CollProxy> class Element, typename MainColl, typename... AuxColls>
410  template <typename Tag, typename T>
412  std::bool_constant<false>) const -> T
413  {
414  throw std::logic_error("Tag '" + lar::debug::demangle<Tag>() + "' not available.");
415  }
416 
417  //----------------------------------------------------------------------------
418 
419 } // namespace proxy
420 
421 #endif // LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXY_H
const_iterator begin() const
Returns an iterator to the first element of the collection.
std::tuple< AuxColls... > aux_collections_t
Tuple of all auxiliary data collections (wrappers).
util::collection_value_t< MainColl > main_element_t
Type of the elements in the original collection.
std::size_t fIndex
Current index in the main collection.
int main()
Definition: example_main.cc:17
CollectionProxyBase< CollectionProxyElement, MainColl, AuxColls... > CollectionProxy
Base representation of a collection of proxied objects.
typename details::TemplateAdaptorOnePlus< CollectionProxy, Args... >::type CollectionProxyFromArgs
CollectionProxyBase(main_collection_t const &main, AuxColls &&...aux)
Constructor: uses the specified data.
auto auxByTag() const -> decltype(auto)
Returns the auxiliary data specified by type.
STL namespace.
intermediate_table::const_iterator const_iterator
const_iterator & operator++()
Returns the value pointed by this iterator.
Iterator to random access collection storing a current index.
Base representation of a collection of proxied objects.
Wrapper for the main collection of a proxy.
auto makeCollectionProxy(MainColl const &main, AuxColl &&...aux)
Creates a CollectionProxy object with the given arguments.
auto createCollectionProxy(MainColl const &main, AuxColl &&...aux)
Creates a collection proxy of a specified type with the given arguments.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
const_iterator makeIterator(std::size_t i) const
Returns an iterator pointing to the specified index of this collection.
Proxy class for charged space point proxy elements.
bool empty() const
Returns whether this collection is empty.
Utilities for the main collection of a collection proxy.
Utilities for a single element of a collection proxy.
auto operator*() const -> decltype(auto)
Returns the value pointed by this iterator.
Encloses LArSoft data product proxy objects and utilities.See this doxygen module for an introduction...
MainColl main_collection_t
Type of the original collection.
const_iterator end() const
Returns an iterator past the last element of the collection.
Traits holding whether elements of Tuple have duplicate types.
container_t const * fCont
Pointer to the original container.
IndexBasedIterator(container_t const &cont, std::size_t index=0)
Constructor: initializes from an iterator of the proxy main collection.
std::size_t size() const
Returns the size of this collection.
static constexpr bool has()
Returns whether this class knowns about the specified type (Tag).
An element of a collection proxy.
auto getIfHas(std::bool_constant< true >) const -> decltype(auto)
element_proxy_t const operator[](std::size_t i) const
Returns the element of this collection with the specified index.
Utilities to address elements of a tuple-like class by tag.
util::collection_value_t< container_t > value_type
AuxColl const & aux() const
Returns the auxiliary data specified by type.
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:62
C++ metaprogramming utilities for dealing with containers.
auto getIf() const -> decltype(auto)
Returns the auxiliary data specified by type (Tag).
bool operator!=(const_iterator const &other) const
Returns whether the iterators point to the same element.