SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
enforce_random_access.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <seqan3/std/iterator>
16 #include <seqan3/std/ranges>
17 #include <seqan3/std/type_traits>
18 
22 
23 namespace seqan3::detail
24 {
25 
26 // ============================================================================
27 // view_pseudo_random_access
28 // ============================================================================
29 
41 template <std::ranges::view urng_t>
45 class view_enforce_random_access : public std::ranges::view_interface<view_enforce_random_access<urng_t>>
46 {
47 private:
48 
49  // Iterator declaration.
50  template <typename underlying_iter_t>
51  class basic_iterator;
52 
53 public:
54 
58  constexpr view_enforce_random_access() = default;
59  constexpr view_enforce_random_access(view_enforce_random_access const &) = default;
60  constexpr view_enforce_random_access(view_enforce_random_access &&) = default;
61  constexpr view_enforce_random_access & operator=(view_enforce_random_access const &) = default;
62  constexpr view_enforce_random_access & operator=(view_enforce_random_access &&) = default;
63  ~view_enforce_random_access() = default;
64 
66  explicit constexpr view_enforce_random_access(urng_t range) : urng{std::move(range)}
67  {}
68 
70  template <typename viewable_rng_t>
72  requires (!std::same_as<std::remove_cvref_t<viewable_rng_t>, view_enforce_random_access>) &&
73  std::ranges::viewable_range<viewable_rng_t> &&
74  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<viewable_rng_t>>>
76  explicit constexpr view_enforce_random_access(viewable_rng_t range) :
77  view_enforce_random_access{std::views::all(range)}
78  {}
80 
85  constexpr auto begin() noexcept
86  {
87  return basic_iterator<decltype(std::ranges::begin(urng))>{std::ranges::begin(urng)};
88  }
89 
91  constexpr auto begin() const noexcept
93  requires const_iterable_range<urng_t>
95  {
96  return basic_iterator<decltype(std::ranges::cbegin(urng))>{std::ranges::cbegin(urng)};
97  }
98 
107  constexpr auto end() noexcept
108  {
109  if constexpr (std::ranges::common_range<urng_t>)
110  return basic_iterator<decltype(std::ranges::end(urng))>{std::ranges::end(urng)};
111  else
112  return urng.end();
113  }
114 
116  constexpr auto end() const noexcept
118  requires const_iterable_range<urng_t>
120  {
121  if constexpr (std::ranges::common_range<urng_t>)
122  return basic_iterator<decltype(std::ranges::cend(urng))>{std::ranges::cend(urng)};
123  else
124  return std::ranges::cend(urng);
125  }
127 
128  urng_t urng;
129 };
130 
139 template <std::ranges::view urng_t>
143 template <typename underlying_iter_t>
144 class view_enforce_random_access<urng_t>::basic_iterator :
145  public inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>
146 {
147 private:
149  using base_t = inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>;
150 
151 public:
152 
154  using iterator_category = std::random_access_iterator_tag;
156  using iterator_concept = iterator_category;
157 
161  // Importing base's constructors.
162  using base_t::base_t;
164  constexpr basic_iterator() = default;
166  constexpr basic_iterator(basic_iterator const &) = default;
168  constexpr basic_iterator(basic_iterator &&) = default;
170  constexpr basic_iterator & operator=(basic_iterator const &) = default;
172  constexpr basic_iterator & operator=(basic_iterator &&) = default;
174  ~basic_iterator() = default;
176 
181  // Importing base's equality operators
182  using base_t::operator==;
183  using base_t::operator!=;
185  friend constexpr bool operator==(basic_iterator const & lhs, std::ranges::sentinel_t<urng_t> const & rhs)
186  noexcept(noexcept(std::declval<underlying_iter_t const &>() ==
187  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
188  {
189  return lhs.base() == rhs;
190  }
191 
193  friend constexpr bool operator==(std::ranges::sentinel_t<urng_t> const & lhs, basic_iterator const & rhs)
194  noexcept(noexcept(std::declval<underlying_iter_t const &>() ==
195  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
196  {
197  return rhs == lhs;
198  }
199 
201  friend constexpr bool operator!=(basic_iterator const & lhs, std::ranges::sentinel_t<urng_t> const & rhs)
202  noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
203  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
204  {
205  return !(lhs == rhs);
206  }
207 
209  friend constexpr bool operator!=(std::ranges::sentinel_t<urng_t> const & lhs, basic_iterator const & rhs)
210  noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
211  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
212  {
213  return rhs != lhs;
214  }
216 
220  // Import operator from base.
221  using base_t::operator-;
222 
224  constexpr typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t> const & rhs) const
225  noexcept(noexcept(std::declval<underlying_iter_t const &>() -
226  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
227  requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
228  {
229  return this->base() - rhs;
230  }
231 
233  constexpr friend typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t> const & lhs,
234  basic_iterator const & rhs)
235  noexcept(noexcept(std::declval<std::ranges::sentinel_t<urng_t> const &>() -
236  std::declval<underlying_iter_t const &>()))
237  requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
238  {
239  return lhs - rhs.base();
240  }
242 };
243 
249 template <std::ranges::viewable_range rng_t>
250 view_enforce_random_access(rng_t &&) -> view_enforce_random_access<std::views::all_t<rng_t>>;
252 
253 // ============================================================================
254 // pseudo_random_access_fn (adaptor definition)
255 // ============================================================================
256 
258 struct pseudo_random_access_fn : public adaptor_base<pseudo_random_access_fn>
259 {
260 private:
262  using base_t = adaptor_base<pseudo_random_access_fn>;
263 
264 public:
266  using base_t::base_t;
267 
268 private:
270  friend base_t;
271 
275  template <std::ranges::viewable_range urng_t>
276  static constexpr auto impl(urng_t && urange)
277  {
278  static_assert(std::ranges::random_access_range<urng_t> || pseudo_random_access_range<urng_t>,
279  "The adapted range must either model std::ranges::random_access_range or must be "
280  "a specific SeqAn range type that supports pseudo random access.");
281  static_assert(std::ranges::forward_range<urng_t>,
282  "The underlying range must model std::ranges::forward_range.");
283 
284  if constexpr (std::ranges::random_access_range<urng_t>)
285  { // Nothing to do, just return as ref_view or original view.
286  return std::views::all(std::forward<urng_t>(urange));
287  }
288  else
289  { // Get a subrange using the random access iterators of the container.
290  return view_enforce_random_access{std::forward<urng_t>(urange)};
291  }
292  }
293 };
294 
295 } // namespace seqan3::detail
296 
297 namespace seqan3::views
298 {
299 
372 inline constexpr auto enforce_random_access = detail::pseudo_random_access_fn{};
374 } // namespace seqan3::views
Provides seqan3::detail::adaptor_base and seqan3::detail::combined_adaptor.
T begin(T... args)
Provides the seqan3::detail::inherited_iterator_base template.
T declval(T... args)
T end(T... args)
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
constexpr auto enforce_random_access
A view adaptor that converts a pseudo random access range to a std::ranges::random_access_range.
Definition: enforce_random_access.hpp:372
Specifies requirements of an input range type for which the const version of that type satisfies the ...
This concept checks if a type models a pseudo random access range.
Provides C++20 additions to the <iterator> header.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Adaptations of concepts from the Ranges TS.
Provides C++20 additions to the type_traits header.
Additional non-standard concepts for ranges.