LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
span.h
Go to the documentation of this file.
1 
10 #ifndef LARCOREALG_COREUTILS_SPAN_H
11 #define LARCOREALG_COREUTILS_SPAN_H
12 
13 // Boost libraries
14 #include "boost/iterator/transform_iterator.hpp"
15 
16 // C/C++ standard library
17 #include <iterator> // std::begin(), std::end()
18 #include <type_traits> // std::decay_t<>, std::declval(), std::invoke_result_t<>
19 #include <utility> // std::as_const()
20 
21 namespace util {
22 
24  struct span_base {
25 
27  template <typename Cont>
28  static decltype(auto) get_begin(Cont& cont)
29  {
30  using std::begin;
31  return begin(cont);
32  }
33 
35  template <typename Cont>
36  static decltype(auto) get_end(Cont& cont)
37  {
38  using std::end;
39  return end(cont);
40  }
41 
43  template <typename Cont>
44  using get_begin_iterator = std::decay_t<decltype(get_begin(std::declval<Cont>()))>;
45 
47  template <typename Cont>
48  using get_end_iterator = std::decay_t<decltype(get_end(std::declval<Cont>()))>;
49 
51  template <typename Cont>
52  static decltype(auto) get_cbegin(Cont& cont)
53  {
54  using std::cbegin;
55  return cbegin(cont);
56  }
57 
59  template <typename Cont>
60  static decltype(auto) get_cend(Cont& cont)
61  {
62  using std::cend;
63  return cend(cont);
64  }
65 
67  template <typename Cont>
68  using get_cbegin_iterator = std::decay_t<decltype(get_cbegin(std::declval<Cont>()))>;
69 
71  template <typename Cont>
72  using get_cend_iterator = std::decay_t<decltype(get_cend(std::declval<Cont>()))>;
73 
74  }; // struct span_base
75 
128  template <typename BIter, typename EIter = BIter>
129  struct span : public span_base, private std::pair<BIter, EIter> {
130 
131  using begin_iterator = BIter;
132  using end_iterator = EIter;
133 
136 
138  using pair_t = std::pair<begin_iterator, end_iterator>;
139 
141  using value_type = typename begin_iterator::value_type;
142 
144  using reference = typename begin_iterator::reference;
145 
148 
150  template <typename SrcIterB, typename SrcIterE, typename Adaptor>
151  span(SrcIterB&& b, SrcIterE&& e, Adaptor&& adaptor)
152  : span(adaptor(std::forward<SrcIterB>(b)), adaptor(std::forward<SrcIterE>(e)))
153  {}
154 
156  template <typename OBIter, typename OEIter>
157  span(span<OBIter, OEIter> const& from) : span(from.begin(), from.end())
158  {}
159 
160  // C++ boilerplate
161  span(span_t const&) = default;
162  span(span_t&&) = default;
163  span_t& operator=(span_t const&) = default;
164  span_t& operator=(span_t&&) = default;
165 
167  begin_iterator begin() const { return pair_t::first; }
168 
170  end_iterator end() const { return pair_t::second; }
171 
173  std::size_t size() const { return std::distance(begin(), end()); }
174 
176  bool empty() const { return begin() == end(); }
177 
178  }; // span
179 
180  // deduction guide for adapted span
181  template <typename IterB, typename IterE, typename Adaptor>
182  span(IterB&& b, IterE&& e, Adaptor&& adaptor) -> span<
183 #if 0 // this is C++17...
184  std::invoke_result_t<Adaptor, IterB>,
185  std::invoke_result_t<Adaptor, IterE>
186 #else // ... and this is what Clang 5.0 undestands
187  decltype(adaptor(std::forward<IterB>(b))),
188  decltype(adaptor(std::forward<IterE>(e)))
189 #endif // 0
190  >;
191 
192  // --- BEGIN -- Span helper functions ----------------------------------------
195 
197  template <typename BIter, typename EIter>
198  auto make_span(BIter begin, EIter end)
199  {
200  return util::span(begin, end);
201  }
202 
204  template <typename Cont>
205  auto make_span(Cont& cont)
206  {
207  return span{span_base::get_begin(cont), span_base::get_end(cont)};
208  }
209 
211  template <typename Cont>
212  auto make_const_span(Cont& cont)
213  {
214  return span{span_base::get_cbegin(cont), span_base::get_cend(cont)};
215  }
216 
218  // --- END -- Span helper functions ------------------------------------------
219 
220  // --- BEGIN -- Adapted span helper functions --------------------------------
223 
226  template <typename BIter, typename EIter, typename Adaptor>
227  auto make_adapted_span(BIter begin, EIter end, Adaptor&& adaptor)
228  {
229  return util::span(adaptor(begin), adaptor(end));
230  }
231 
263  template <typename Cont, typename Adaptor>
264  auto make_adapted_span(Cont& cont, Adaptor&& adaptor)
265  {
266  return make_adapted_span(
267  span_base::get_begin(cont), span_base::get_end(cont), std::forward<Adaptor>(adaptor));
268  }
269 
271  // @see `make_adapted_span(Cont, Adaptor&&)`
272  template <typename Cont, typename Adaptor>
273  auto make_adapted_const_span(Cont& cont, Adaptor&& adaptor)
274  {
275  return make_adapted_span(
276  span_base::get_cbegin(cont), span_base::get_cend(cont), std::forward<Adaptor>(adaptor));
277  }
278 
280  // --- END -- Adapted span helper functions ----------------------------------
281 
282  // --- BEGIN -- Transformed span helper functions ----------------------------
289 
293  template <typename BIter, typename EIter, typename Op>
294  auto make_transformed_span(BIter begin, EIter end, Op&& op)
295  {
296  auto adaptor = [&op](auto iter) { return boost::make_transform_iterator(iter, op); };
297  return util::make_adapted_span(begin, end, adaptor);
298  }
299 
338  template <typename Cont, typename Op>
339  auto make_transformed_span(Cont& cont, Op&& op)
340  {
341  return make_transformed_span(
342  span_base::get_begin(cont), span_base::get_end(cont), std::forward<Op>(op));
343  }
344 
347  // @see `make_transformed_span(Cont, Op&&)`
348  template <typename Cont, typename Op>
349  auto make_transformed_const_span(Cont& cont, Op&& op)
350  {
351  return make_transformed_span(std::as_const(cont), std::forward<Op>(op));
352  }
353 
355  // --- END -- Adapted span helper functions ----------------------------------
356 
357 } // namespace util
358 
359 #endif // LARCOREALG_COREUTILS_SPAN_H
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
bool empty() const
Returns whether the span is empty (that is, no steps between them).
Definition: span.h:176
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Definition: StdUtils.h:93
span(begin_iterator b, end_iterator e)
Constructor: specifies the begin and end iterator.
Definition: span.h:147
span(SrcIterB &&b, SrcIterE &&e, Adaptor &&adaptor)
Constructor: specifies the begin and end iterator and an adapter.
Definition: span.h:151
static decltype(auto) get_begin(Cont &cont)
Returns the begin iterator of the specified container.
Definition: span.h:28
auto make_span(BIter begin, EIter end)
Creates a span from specified iterators (can use constructor instead).
Definition: span.h:198
std::decay_t< decltype(get_end(std::declval< Cont >()))> get_end_iterator
Type of end iterator of Cont type.
Definition: span.h:48
STL namespace.
typename begin_iterator::value_type value_type
Type of values pointed by the iterators.
Definition: span.h:141
end_iterator end() const
Returns a copy of the end iterator.
Definition: span.h:170
Simple class with a begin and an end.
Definition: span.h:129
auto make_adapted_span(BIter begin, EIter end, Adaptor &&adaptor)
Definition: span.h:227
EIter end_iterator
Type of end iterator.
Definition: span.h:132
span(span< OBIter, OEIter > const &from)
Constructor: copies from another span (possibly with different types).
Definition: span.h:157
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
static decltype(auto) get_cbegin(Cont &cont)
Returns the constant begin iterator of the specified container.
Definition: span.h:52
static decltype(auto) get_cend(Cont &cont)
Returns the constant end iterator of the specified container.
Definition: span.h:60
BIter begin_iterator
Type of begin iterator.
Definition: span.h:131
auto make_transformed_const_span(Cont &cont, Op &&op)
Definition: span.h:349
std::decay_t< decltype(get_cbegin(std::declval< Cont >()))> get_cbegin_iterator
Type of constant begin iterator of Cont type.
Definition: span.h:68
auto make_transformed_span(BIter begin, EIter end, Op &&op)
Definition: span.h:294
static decltype(auto) get_end(Cont &cont)
Returns the end iterator of the specified container.
Definition: span.h:36
std::size_t size() const
Returns the size between begin and end, converted to std::size_t.
Definition: span.h:173
typename begin_iterator::reference reference
Type of reference pointed by the iterators.
Definition: span.h:144
begin_iterator begin() const
Returns a copy of the begin iterator.
Definition: span.h:167
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:85
std::pair< begin_iterator, end_iterator > pair_t
Type of iterator pair.
Definition: span.h:138
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
Float_t e
Definition: plot.C:35
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
Non-templated base class for span.
Definition: span.h:24
std::decay_t< decltype(get_begin(std::declval< Cont >()))> get_begin_iterator
Type of begin iterator of Cont type.
Definition: span.h:44
std::decay_t< decltype(get_cend(std::declval< Cont >()))> get_cend_iterator
Type of constant end iterator of Cont type.
Definition: span.h:72
auto make_const_span(Cont &cont)
Creates a span with constant iterator access from a container type.
Definition: span.h:212
auto make_adapted_const_span(Cont &cont, Adaptor &&adaptor)
Creates constant iteration span from specified collection via an adaptor.
Definition: span.h:273