LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ContainerMeta.h
Go to the documentation of this file.
1 
9 #ifndef LARCOREALG_COREUTILS_CONTAINERMETA_H
10 #define LARCOREALG_COREUTILS_CONTAINERMETA_H
11 
12 // LArSoft
13 #include "larcorealg/CoreUtils/MetaUtils.h" // for Doxygen documentation
14 
15 // C/C++ standard libraries
16 #include <functional> // std::reference_wrapper<>
17 #include <iterator> // std::begin(), std::cbegin()
18 #include <memory> // std::unique_ptr<>
19 #include <type_traits> // std::enable_if_t<>
20 #include <utility> // std::declval()
21 
22 namespace util {
23 
24  //--- BEGIN ContainerMetaprogramming -----------------------------------------
53 
55  //----------------------------------------------------------------------------
57  template <typename Coll>
59 
61  template <typename Coll>
63 
64  //----------------------------------------------------------------------------
66  template <typename Coll>
68 
70  template <typename Coll>
72 
73  //----------------------------------------------------------------------------
75  template <typename Coll>
77 
79  template <typename Coll>
82 
83  //----------------------------------------------------------------------------
98  template <typename Coll>
100 
102  template <typename Coll>
104 
119  template <typename Coll>
120  auto make_collection_reference(Coll&& coll);
121 
134  template <typename Cont>
136 
138  template <typename Cont>
140 
155  template <typename CollRef>
156  decltype(auto) collection_from_reference(CollRef& collRef);
157 
159  //--- END ContainerMetaprogramming -------------------------------------------
160 
161 } // namespace util
162 
163 //------------------------------------------------------------------------------
164 //--- template implementation
165 //------------------------------------------------------------------------------
166 namespace util {
167 
168  namespace details {
169 
170  //--------------------------------------------------------------------------
171  //--- collection_value_XXXX
172  //--------------------------------------------------------------------------
173  template <typename Ptr>
175 
176  template <typename T>
178  using type = T;
179  using value_type = type;
180  }; // struct collection_value_type_impl_pointer<T*>
181 
182  template <typename T>
184  using type = T;
185  using value_type = type;
186  }; // struct collection_value_type_impl_pointer<T[]>
187 
188  template <typename T, std::size_t N>
190  using type = T;
191  using value_type = type;
192  }; // struct collection_value_type_impl_pointer<T[N]>
193 
194  template <typename Ptr, typename = void>
196  : collection_value_type_impl_pointer<typename Ptr::pointer> {};
197 
198  template <typename Coll, typename = void>
200  using type = typename Coll::value_type;
201  using value_type = type;
202  }; // struct collection_value_type_impl
203 
204  template <typename Coll>
205  struct collection_value_type_impl<Coll, std::enable_if_t<std::is_pointer_v<std::decay_t<Coll>>>>
206  : collection_value_type_impl_pointer<std::decay_t<Coll>> {};
207 
208  template <typename Coll>
210  std::enable_if_t<util::is_unique_ptr_v<std::decay_t<Coll>>>>
211  : collection_value_type_impl_unique_ptr<std::decay_t<Coll>> {};
212 
213  //--------------------------------------------------------------------------
214  template <typename Coll, typename = void>
216  private:
217  static auto getBegin(Coll&& coll)
218  {
219  using std::begin;
220  return begin(coll);
221  }
222 
223  public:
224  using type = decltype(*getBegin(std::declval<Coll>()));
226 
227  }; // struct collection_value_access_type_impl
228 
229  template <typename T>
231  using type = decltype(*(std::declval<T*>()));
232  using value_type = T;
233  }; // struct collection_value_access_type_impl<T*>
234 
235  template <typename Ptr>
237  Ptr,
238  std::enable_if_t<util::is_unique_ptr_v<std::decay_t<Ptr>>>>
239  : collection_value_access_type_impl<std::remove_reference_t<typename Ptr::pointer>> {};
240 
241  //--------------------------------------------------------------------------
242  template <typename Coll, typename = void>
244  private:
245  static auto getCBegin(Coll&& coll)
246  {
247  using std::cbegin;
248  return cbegin(coll);
249  }
250 
251  public:
252  using type = decltype(*getCBegin(std::declval<Coll>()));
254 
255  }; // struct collection_value_constant_access_type_impl
256 
257  template <typename T>
259  using type = decltype(*(std::declval<std::add_const_t<T>*>()));
260  using value_type = std::add_const_t<T>;
261  }; // struct collection_value_constant_access_type_impl
262 
263  template <typename Ptr>
265  Ptr,
266  std::enable_if_t<util::is_unique_ptr_v<std::decay_t<Ptr>>>>
267  : collection_value_constant_access_type_impl<std::remove_reference_t<typename Ptr::pointer>> {
268  };
269 
270  //--------------------------------------------------------------------------
271  //--- util::make_collection_reference
272 
273  template <typename Coll, typename = void>
275  using type = std::reference_wrapper<Coll>;
276  static auto make(Coll& coll) { return std::ref(coll); }
277  }; // make_collection_reference_impl
278 
279  template <typename Coll>
281  std::enable_if_t<util::is_reference_wrapper_v<Coll>>> {
282  using type = std::remove_cv_t<Coll>;
283  static type make(Coll& refw) { return refw; }
284  }; // make_collection_reference_impl<std::reference_wrapper>
285 
286  template <typename Coll>
287  struct make_collection_reference_impl<Coll, std::enable_if_t<util::is_unique_ptr_v<Coll>>> {
288  using type = typename Coll::pointer;
289  static type make(Coll& uptr) { return uptr.get(); }
290  }; // make_collection_reference_impl<std::unique_ptr>
291 
292  template <typename Ptr>
294  std::enable_if_t<std::is_pointer_v<std::decay_t<Ptr>>>> {
295  using type = std::add_pointer_t< // finally add the pointer
296  std::remove_all_extents_t< // if it's a C array
297  std::remove_pointer_t<std::decay_t<Ptr>>>>;
298  static type make(Ptr& ptr) { return ptr; }
299  }; // make_collection_reference_impl<std::unique_ptr>
300 
301  //--------------------------------------------------------------------------
302  //--- util::collection_from_reference
303 
304  template <typename CollRef, typename = void>
306  using type = std::add_lvalue_reference_t<std::remove_reference_t<CollRef>>;
307  static CollRef& get(CollRef& coll) { return coll; }
308  }; // collection_from_reference_impl
309 
310  template <typename CollRef>
312  std::enable_if_t<util::is_reference_wrapper_v<CollRef>>> {
313  using type = std::add_lvalue_reference_t<typename CollRef::type>;
314  static type get(CollRef& refw) { return refw.get(); }
315  }; // collection_from_reference_impl<std::reference_wrapper>
316 
317  template <typename CollRef>
319  std::enable_if_t<util::is_unique_ptr_v<CollRef>>> {
320  using type = typename CollRef::pointer;
321  static type get(CollRef& uptr) { return uptr.get(); }
322  }; // collection_from_reference_impl<std::unique_ptr>
323 
324  template <typename T>
326  using type = T*;
327  static type get(T* ptr) { return ptr; }
328  }; // collection_from_reference_impl<T*>
329 
330  template <typename T>
332  using type = T*;
333  static type get(T ptr[]) { return ptr; }
334  }; // collection_from_reference_impl<T[]>
335 
336  template <typename T, std::size_t N>
338  using type = T*;
339  static type get(T ptr[N]) { return ptr; }
340  }; // collection_from_reference_impl<T[N]>
341 
342  //--------------------------------------------------------------------------
343 
344  } // namespace details
345 
346  //----------------------------------------------------------------------------
347  template <typename Coll>
348  struct collection_value_type {
349  // remove all referenceness, constantness etc. from `Coll`;
350  // also remove all referenceness from the result
353  };
354 
355  //----------------------------------------------------------------------------
356  template <typename Coll>
358  : public details::collection_value_access_type_impl<util::strip_referenceness_t<Coll>> {};
359 
360  //----------------------------------------------------------------------------
361  template <typename Coll>
364  util::strip_referenceness_t<Coll>> {};
365 
366  //----------------------------------------------------------------------------
367  template <typename Coll>
369  : details::make_collection_reference_impl<std::remove_reference_t<Coll>> {};
370 
371  //----------------------------------------------------------------------------
372  template <typename Coll>
373  auto make_collection_reference(Coll&& coll)
374  {
376  }
377 
378  //----------------------------------------------------------------------------
379  template <typename CollRef>
381  : details::collection_from_reference_impl<std::remove_reference_t<CollRef>> {};
382 
383  //----------------------------------------------------------------------------
384  template <typename CollRef>
385  decltype(auto) collection_from_reference(CollRef& collRef)
386  {
388  }
389 
390  //----------------------------------------------------------------------------
391 
392 } // namespace util
393 
394 //------------------------------------------------------------------------------
395 
396 #endif // LARCOREALG_COREUTILS_CONTAINERMETA_H
auto make_collection_reference(Coll &&coll)
Returns an object referencing to the data contained in coll.
static CollRef & get(CollRef &coll)
typename collection_value_access_type< Coll >::type collection_value_access_t
Type obtained by constant access to element of collection Coll.
Definition: ContainerMeta.h:71
typename strip_referenceness_type< T >::type strip_referenceness_t
The type T stripped of all known reference types.
Definition: MetaUtils.h:539
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
Basic C++ metaprogramming utilities.
std::unique_ptr< InputSource > make(fhicl::ParameterSet const &conf, InputSourceDescription &desc)
Trait of type obtained by constant access to element of collection Coll.
Definition: ContainerMeta.h:76
std::add_lvalue_reference_t< std::remove_reference_t< std::remove_reference_t< CollRef > >> type
STL namespace.
Trait with the type of collection referenced by collRef.
Trait of type obtained by access to element of collection Coll.
Definition: ContainerMeta.h:67
typename collection_reference_type< Coll >::type collection_reference_t
The type contained in util::collection_reference_type trait.
collection_value_t< std::remove_reference_t< Ptr::pointer > > value_type
Ptr(H, T) -> Ptr< detail::not_map_vector_t< typename H::element_type >>
Trait of a type that can be used to reference the collection Coll.
Definition: ContainerMeta.h:99
typename collection_from_reference_type< Cont >::type collection_from_reference_t
Type contained in util::collection_from_reference_type trait.
decltype(*getBegin(std::declval< util::strip_referenceness_t< Coll > >())) type
std::reference_wrapper< std::remove_reference_t< Coll > > type
decltype(*getCBegin(std::declval< util::strip_referenceness_t< Coll > >())) type
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:85
util::strip_referenceness_t< typename details::collection_value_type_impl< util::strip_referenceness_t< Coll >>::type > type
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:62
decltype(auto) collection_from_reference(CollRef &collRef)
Returns the object referenced by collRef as a C++ reference.
typename collection_value_constant_access_type< Coll >::type collection_value_constant_access_t
Type obtained by constant access to element of collection Coll.
Definition: ContainerMeta.h:81
Trait of value contained in the template collection Coll.
Definition: ContainerMeta.h:58