LArSoft  v10_04_05
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)
183  -> span<std::invoke_result_t<Adaptor, IterB>, std::invoke_result_t<Adaptor, IterE>>;
184 
185  // --- BEGIN -- Span helper functions ----------------------------------------
188 
190  template <typename BIter, typename EIter>
191  auto make_span(BIter begin, EIter end)
192  {
193  return span{begin, end};
194  }
195 
197  template <typename Cont>
198  auto make_span(Cont& cont)
199  {
200  return span{span_base::get_begin(cont), span_base::get_end(cont)};
201  }
202 
204  template <typename Cont>
205  auto make_const_span(Cont& cont)
206  {
207  return span{span_base::get_cbegin(cont), span_base::get_cend(cont)};
208  }
209 
211  // --- END -- Span helper functions ------------------------------------------
212 
213  // --- BEGIN -- Adapted span helper functions --------------------------------
216 
219  template <typename BIter, typename EIter, typename Adaptor>
220  auto make_adapted_span(BIter begin, EIter end, Adaptor&& adaptor)
221  {
222  return util::span(adaptor(begin), adaptor(end));
223  }
224 
256  template <typename Cont, typename Adaptor>
257  auto make_adapted_span(Cont& cont, Adaptor&& adaptor)
258  {
259  return make_adapted_span(
260  span_base::get_begin(cont), span_base::get_end(cont), std::forward<Adaptor>(adaptor));
261  }
262 
264  // @see `make_adapted_span(Cont, Adaptor&&)`
265  template <typename Cont, typename Adaptor>
266  auto make_adapted_const_span(Cont& cont, Adaptor&& adaptor)
267  {
268  return make_adapted_span(
269  span_base::get_cbegin(cont), span_base::get_cend(cont), std::forward<Adaptor>(adaptor));
270  }
271 
273  // --- END -- Adapted span helper functions ----------------------------------
274 
275  // --- BEGIN -- Transformed span helper functions ----------------------------
282 
286  template <typename BIter, typename EIter, typename Op>
287  auto make_transformed_span(BIter begin, EIter end, Op&& op)
288  {
289  auto adaptor = [&op](auto iter) { return boost::make_transform_iterator(iter, op); };
290  return util::make_adapted_span(begin, end, adaptor);
291  }
292 
331  template <typename Cont, typename Op>
332  auto make_transformed_span(Cont& cont, Op&& op)
333  {
334  return make_transformed_span(
335  span_base::get_begin(cont), span_base::get_end(cont), std::forward<Op>(op));
336  }
337 
340  // @see `make_transformed_span(Cont, Op&&)`
341  template <typename Cont, typename Op>
342  auto make_transformed_const_span(Cont& cont, Op&& op)
343  {
344  return make_transformed_span(std::as_const(cont), std::forward<Op>(op));
345  }
346 
348  // --- END -- Adapted span helper functions ----------------------------------
349 
350 } // namespace util
351 
352 #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:191
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:220
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
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< std::invoke_result_t< Adaptor, IterB >, std::invoke_result_t< Adaptor, IterE >>
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:342
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:287
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
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:205
auto make_adapted_const_span(Cont &cont, Adaptor &&adaptor)
Creates constant iteration span from specified collection via an adaptor.
Definition: span.h:266