Horizon
iterator_range.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2013-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 
14 #ifndef RANGES_V3_ITERATOR_RANGE_HPP
15 #define RANGES_V3_ITERATOR_RANGE_HPP
16 
17 #include <type_traits>
18 #include <utility>
19 
20 #include <meta/meta.hpp>
21 
22 #include <concepts/concepts.hpp>
23 
24 #include <range/v3/range_fwd.hpp>
25 
29 #include <range/v3/utility/static_const.hpp>
31 
33  "This header is deprecated. Please switch to subrange in "
34  "<range/v3/view/subrange.hpp>.")
35 
36 #include <range/v3/detail/prologue.hpp>
37 
38 namespace ranges
39 {
42 
43  template<typename I, typename S>
44  RANGES_INLINE_VAR constexpr bool enable_borrowed_range<iterator_range<I, S>> = true;
45 
46  template<typename I, typename S>
47  RANGES_INLINE_VAR constexpr bool enable_borrowed_range<sized_iterator_range<I, S>> =
48  true;
49 
50  template<typename I, typename S /*= I*/>
51  struct RANGES_EMPTY_BASES iterator_range
52  : view_interface<iterator_range<I, S>,
53  same_as<S, unreachable_sentinel_t> ? infinite : unknown>
54  , compressed_pair<I, S>
55  {
56  private:
57  template<typename, typename>
58  friend struct iterator_range;
59  template<typename, typename>
60  friend struct sized_iterator_range;
61  compressed_pair<I, S> & base() noexcept
62  {
63  return *this;
64  }
65  compressed_pair<I, S> const & base() const noexcept
66  {
67  return *this;
68  }
71 
72  public:
73  using iterator = I;
74  using sentinel = S;
76  using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
78 
79  constexpr I & begin() &
80  {
81  return this->first();
82  }
83  constexpr I const & begin() const &
84  {
85  return this->first();
86  }
87 
88  constexpr S & end() &
89  {
90  return this->second();
91  }
92  constexpr S const & end() const &
93  {
94  return this->second();
95  }
96 
97  iterator_range() = default;
98  constexpr iterator_range(I first, S last)
99  : compressed_pair<I, S>{detail::move(first), detail::move(last)}
100  {}
101  template(typename X, typename Y)(
102  requires constructible_from<I, X> AND constructible_from<S, Y>)
103  constexpr iterator_range(iterator_range<X, Y> rng)
104  : compressed_pair<I, S>{detail::move(rng.begin()), detail::move(rng.end())}
105  {}
106  template(typename X, typename Y)(
107  requires constructible_from<I, X> AND constructible_from<S, Y>)
108  constexpr explicit iterator_range(std::pair<X, Y> rng)
109  : compressed_pair<I, S>{detail::move(rng.first), detail::move(rng.second)}
110  {}
111  template(typename X, typename Y)(
112  requires assignable_from<I &, X> AND assignable_from<S &, Y>)
113  iterator_range & operator=(iterator_range<X, Y> rng)
114  {
115  base().first() = std::move(rng.base()).first();
116  base().second() = std::move(rng.base()).second();
117  return *this;
118  }
119  template(typename X, typename Y)(
120  requires convertible_to<I, X> AND convertible_to<S, Y>)
121  constexpr operator std::pair<X, Y>() const
122  {
123  return {base().first(), base().second()};
124  }
125  constexpr bool empty() const
126  {
127  return base().first() == base().second();
128  }
129  };
130 
131  // Like iterator_range, but with a known size. The first and second members
132  // are private to prevent inadvertent violations of the class invariant.
133  //
134  // Class invariant:
135  // distance(begin(), end()) == size()
136  //
137  template<typename I, typename S /* = I */>
138  struct sized_iterator_range
139  : view_interface<sized_iterator_range<I, S>, finite>
140  {
141  using size_type = detail::iter_size_t<I>;
142  using iterator = I;
143  using sentinel = S;
144 #ifndef RANGES_DOXYGEN_INVOKED
145  using const_iterator = I; // Mostly to avoid spurious errors in Boost.Range
146 #endif
147 
148  private:
149  template<typename X, typename Y>
150  friend struct sized_iterator_range;
151  iterator_range<I, S> rng_;
152  size_type size_;
153 
154  public:
155  sized_iterator_range() = default;
156  RANGES_NDEBUG_CONSTEXPR sized_iterator_range(I first, S last, size_type size)
157  : rng_{detail::move(first), detail::move(last)}
158  , size_(size)
159  {
160 #ifndef NDEBUG
161  RANGES_ASSERT(!(bool)forward_iterator<I> ||
162  static_cast<size_type>(ranges::distance(rng_)) == size_);
163 #endif
164  }
165  template(typename X, typename Y)(
166  requires constructible_from<I, X> AND constructible_from<S, Y>)
167  RANGES_NDEBUG_CONSTEXPR sized_iterator_range(std::pair<X, Y> rng, size_type size)
168  : sized_iterator_range{detail::move(rng).first, detail::move(rng).second, size}
169  {}
170  template(typename X, typename Y)(
171  requires constructible_from<I, X> AND constructible_from<S, Y>)
172  RANGES_NDEBUG_CONSTEXPR sized_iterator_range(iterator_range<X, Y> rng,
173  size_type size)
174  : sized_iterator_range{detail::move(rng).first(),
175  detail::move(rng).second,
176  size}
177  {}
178  template(typename X, typename Y)(
179  requires constructible_from<I, X> AND constructible_from<S, Y>)
180  RANGES_NDEBUG_CONSTEXPR sized_iterator_range(sized_iterator_range<X, Y> rng)
181  : sized_iterator_range{detail::move(rng).rng_.first(),
182  detail::move(rng).rng_.second,
183  rng.size_}
184  {}
185  template(typename X, typename Y)(
186  requires assignable_from<I &, X> AND assignable_from<S &, Y>)
187  sized_iterator_range & operator=(sized_iterator_range<X, Y> rng)
188  {
189  rng_ = detail::move(rng).rng_;
190  size_ = rng.size_;
191  return *this;
192  }
193  I begin() const
194  {
195  return rng_.begin();
196  }
197  S end() const
198  {
199  return rng_.end();
200  }
201  size_type size() const noexcept
202  {
203  return size_;
204  }
205  template(typename X, typename Y)(
206  requires convertible_to<I, X> AND convertible_to<S, Y>)
207  constexpr operator std::pair<X, Y>() const
208  {
209  return rng_;
210  }
211  template(typename X, typename Y)(
212  requires convertible_to<I, X> AND convertible_to<S, Y>)
213  constexpr operator iterator_range<X, Y>() const
214  {
215  return rng_;
216  }
217  constexpr operator iterator_range<I, S> const &() const & noexcept
218  {
219  return rng_;
220  }
221  // clang-format off
223  template(std::size_t N)(
224  requires (N < 2)) //
225  friend constexpr auto CPP_auto_fun(get)(sized_iterator_range const &p)
226  (
227  // return ranges::get<N>(p.rng_)
228  return ranges::get<N>(p.*&sized_iterator_range::rng_) // makes clang happy
229  )
230  // clang-format on
232  template(std::size_t N)(
233  requires (N == 2)) //
234  friend constexpr size_type get(sized_iterator_range const & p) noexcept
235  {
236  return p.size();
237  }
238  };
239 
240  struct make_iterator_range_fn
241  {
243  template(typename I, typename S)(
244  requires sentinel_for<S, I>)
245  constexpr iterator_range<I, S> operator()(I first, S last) const
246  {
247  return {detail::move(first), detail::move(last)};
248  }
249 
251  template(typename I, typename S)(
252  requires sentinel_for<S, I>)
253  constexpr sized_iterator_range<I, S> //
254  operator()(I first, S last, detail::iter_size_t<I> sz) const
255  {
256  return {detail::move(first), detail::move(last), sz};
257  }
258  };
259 
261  RANGES_INLINE_VARIABLE(make_iterator_range_fn, make_iterator_range)
262 
263  // TODO add specialization of range_cardinality for when we can determine the range is
264  // infinite
265 
266 
267 } // namespace ranges
268 
269 // The standard is inconsistent about whether these are classes or structs
270 RANGES_DIAGNOSTIC_PUSH
271 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
272 
274 namespace std
275 {
276  template<typename I, typename S>
277  struct tuple_size<::ranges::iterator_range<I, S>> : std::integral_constant<size_t, 2>
278  {};
279 
280  template<typename I, typename S>
281  struct tuple_element<0, ::ranges::iterator_range<I, S>>
282  {
283  using type = I;
284  };
285 
286  template<typename I, typename S>
287  struct tuple_element<1, ::ranges::iterator_range<I, S>>
288  {
289  using type = S;
290  };
291 
292  template<typename I, typename S>
293  struct tuple_size<::ranges::sized_iterator_range<I, S>>
294  : std::integral_constant<size_t, 3>
295  {};
296 
297  template<typename I, typename S>
298  struct tuple_element<0, ::ranges::sized_iterator_range<I, S>>
299  {
300  using type = I;
301  };
302 
303  template<typename I, typename S>
304  struct tuple_element<1, ::ranges::sized_iterator_range<I, S>>
305  {
306  using type = S;
307  };
308 
309  template<typename I, typename S>
310  struct tuple_element<2, ::ranges::sized_iterator_range<I, S>>
311  {
312  using type = typename ::ranges::sized_iterator_range<I, S>::size_type;
313  };
314 } // namespace std
316 
317 RANGES_DIAGNOSTIC_POP
318 
319 #include <range/v3/detail/epilogue.hpp>
320 
321 #endif
CPP_concept type
\concept type
Definition: concepts.hpp:838
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
RANGES_DEPRECATED_HEADER("This header is deprecated and will be removed from a future version of range-v3.") namespace ranges
Definition: nullptr_v.hpp:17
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
front< pop_front< Pair > > second
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2256
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
Tiny meta-programming library.
Definition: range_fwd.hpp:591