LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
OneTo01Data.h
Go to the documentation of this file.
1 
11 #ifndef LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
12 #define LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
13 
14 // LArSoft libraries
16 #include "lardata/Utilities/TupleLookupByTag.h" // util::add_tag_t(), ...
17 
18 // framework libraries
21 
22 // C/C++ standard
23 #include <cstdlib> // std::size_t
24 #include <iterator> // std::cbegin(), std::cend()
25 #include <tuple> // std::tuple_element_t<>, std::get()
26 #include <type_traits> // std::is_convertible<>
27 #include <utility> // std::move()
28 #include <vector>
29 
30 namespace proxy {
31 
32  namespace details {
33 
66  template <typename Main, typename Aux, typename Metadata /* = void */, typename Tag /* = Aux */
67  >
68  class OneTo01Data {
70 
71  public:
73  using aux_t = Aux;
74 
76  using metadata_t = Metadata;
77 
79  using tag = Tag;
80 
82  using main_t = Main;
83 
86 
89 
91  using aux_coll_t = std::vector<aux_ptr_t>;
92 
95 
96  OneTo01Data(aux_coll_t&& data) : auxData(std::move(data)) {}
97 
99  bool has(std::size_t i) const { return get(i) == aux_ptr_t(); }
100 
102  auxiliary_data_t get(std::size_t i) const { return auxiliary_data_t(auxData[i]); }
103 
105  auto operator[](std::size_t index) const -> decltype(auto)
106  {
107  static_assert(std::is_convertible<decltype(get(index)), auxiliary_data_t>(),
108  "Inconsistent data types.");
109  return get(index);
110  }
111 
112  private:
114 
115  }; // class OneTo01Data<>
116 
117  } // namespace details
118 
120 
154  template <typename Tag, typename Assns>
155  auto makeOneTo01data(Assns const& assns, std::size_t minSize = 0);
156 
157  template <typename Assns>
158  auto makeOneTo01data(Assns const& assns, std::size_t minSize = 0)
159  {
160  return makeOneTo01data<typename Assns::right_t>(assns, minSize);
161  }
163 
165 
183  template <typename Tag, typename MainColl, typename Assns>
184  auto makeOneTo01data(MainColl const& mainColl, Assns const& assns)
185  {
186  return makeOneTo01data<Tag>(assns, mainColl.size());
187  }
188 
189  template <typename MainColl, typename Assns>
190  auto makeOneTo01data(MainColl const& mainColl, Assns const& assns)
191  {
192  return makeOneTo01data<typename Assns::right_t>(mainColl, assns);
193  }
195 
196 } // namespace proxy
197 
198 //------------------------------------------------------------------------------
199 //--- template implementation
200 //------------------------------------------------------------------------------
201 namespace proxy {
202 
203  namespace details {
204 
205  //--------------------------------------------------------------------------
206  // Extends vector v with default-constructed data
207  // and executes v[index]=value
208  template <typename T>
209  void extendAndAssign(std::vector<T>& v,
210  typename std::vector<T>::size_type index,
211  typename std::vector<T>::value_type const& value)
212  {
213  if (index >= v.size()) {
214  v.reserve(index + 1);
215  v.resize(index);
216  v.push_back(value);
217  }
218  else
219  v[index] = value;
220  } // extendAndAssign()
221 
222  // Extends vector v with default-constructed data
223  // and executes v[index]=move(value)
224  template <typename T>
225  void extendAndAssign(std::vector<T>& v,
226  typename std::vector<T>::size_type index,
227  typename std::vector<T>::value_type&& value)
228  {
229  if (index >= v.size()) {
230  v.reserve(index + 1);
231  v.resize(index);
232  v.push_back(std::move(value));
233  }
234  else
235  v[index] = std::move(value);
236  } // extendAndAssign()
237 
238  //--------------------------------------------------------------------------
239  template <std::size_t Key, std::size_t Data, typename Iter>
240  auto associationOneToOneFullSequence(Iter begin, Iter end, std::size_t n)
241  {
242  //
243  // Here we are actually not using the assumption that the keys are in
244  // increasing order; which is just as good as long as we use a fast random
245  // access container as STL vector.
246  // We do assume the key side of the association to be valid, though.
247  //
248  using value_type = typename Iter::value_type;
249  using data_t = std::tuple_element_t<Data, value_type>;
250  std::vector<data_t> data(n); // all default-constructed
251  for (auto it = begin; it != end; ++it) {
252  auto const& keyPtr = std::get<Key>(*it);
253  extendAndAssign(data, keyPtr.key(), std::get<Data>(*it));
254  }
255  return data;
256  } // associationOneToOneFullSequence(Iter, Iter, std::size_t)
257 
258  } // namespace details
259 
260  //----------------------------------------------------------------------------
261  //--- makeOneTo01data() implementation
262  //----------------------------------------------------------------------------
263  template <typename Tag, typename Assns>
264  auto makeOneTo01data(Assns const& assns, std::size_t minSize /* = 0 */)
265  {
266  using Main_t = typename Assns::left_t;
267  using Aux_t = typename Assns::right_t;
268  using Metadata_t = lar::util::assns_metadata_t<Assns>;
270 
271  using std::cbegin;
272  using std::cend;
273  return AssociatedData_t(
274  details::associationOneToOneFullSequence<0U, 1U>(cbegin(assns), cend(assns), minSize));
275  } // makeOneTo01data(assns)
276 
277  //----------------------------------------------------------------------------
278 
279 } // namespace proxy
280 
281 #endif // LARDATA_RECOBASEPROXY_PROXYBASE_ONETO01DATA_H
auto makeOneTo01data(Assns const &assns, std::size_t minSize=0)
Processes and returns an one-to-(zero/one) associated data object.
Definition: OneTo01Data.h:264
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Definition: StdUtils.h:93
art::Ptr< aux_t > aux_ptr_t
Type of art pointer to associated datum.
Definition: OneTo01Data.h:85
bool has(std::size_t i) const
Returns whether the element i is associated with auxiliary datum.
Definition: OneTo01Data.h:99
typename assns_metadata_type< Assns >::type assns_metadata_t
Trait: type of metadata in Assns (association or its node).
Definition: AssnsTraits.h:59
STL namespace.
OneTo01Data(aux_coll_t &&data)
Definition: OneTo01Data.h:96
Main main_t
Type of main datum.
Definition: OneTo01Data.h:82
typename add_tag< T, Tag >::type add_tag_t
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
Tag tag
Type of tag.
Definition: OneTo01Data.h:79
Object for one-to-zero/or/one associated data interface.
Definition: OneTo01Data.h:68
Encloses LArSoft data product proxy objects and utilities.See this doxygen module for an introduction...
Aux aux_t
Type of associated datum.
Definition: OneTo01Data.h:73
double value
Definition: spectrum.C:18
auto operator[](std::size_t index) const -> decltype(auto)
Returns the range with the specified index (no check performed).
Definition: OneTo01Data.h:105
Utilities to address elements of a tuple-like class by tag.
Traits for art associations.
Metadata metadata_t
Type of associated metadata.
Definition: OneTo01Data.h:76
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:85
Char_t n[5]
void extendAndAssign(std::vector< T > &v, typename std::vector< T >::size_type index, typename std::vector< T >::value_type const &value)
Definition: OneTo01Data.h:209
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
std::vector< aux_ptr_t > aux_coll_t
Type of collection of auxiliary data for all main elements.
Definition: OneTo01Data.h:91
aux_coll_t auxData
Data associated to the main collection.
Definition: OneTo01Data.h:113
util::add_tag_t< aux_ptr_t, tag > auxiliary_data_t
Type of auxiliary data associated with a main item.
Definition: OneTo01Data.h:88
Definition: fwd.h:26
auto associationOneToOneFullSequence(Iter begin, Iter end, std::size_t n)
Definition: OneTo01Data.h:240