SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
enforce_random_access.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
17 #include <seqan3/range/concept.hpp>
18 #include <seqan3/std/iterator>
19 #include <seqan3/std/ranges>
20 
21 namespace seqan3::detail
22 {
23 
24 // ============================================================================
25 // view_pseudo_random_access
26 // ============================================================================
27 
39 template <std::ranges::view urng_t>
43 class view_enforce_random_access : public ranges::view_interface<view_enforce_random_access<urng_t>>
44 {
45 private:
46 
47  // Iterator declaration.
48  template <typename underlying_iter_t>
49  class enforced_random_access_iterator;
50 
51 public:
52 
56  constexpr view_enforce_random_access() = default;
57  constexpr view_enforce_random_access(view_enforce_random_access const &) = default;
58  constexpr view_enforce_random_access(view_enforce_random_access &&) = default;
59  constexpr view_enforce_random_access & operator=(view_enforce_random_access const &) = default;
60  constexpr view_enforce_random_access & operator=(view_enforce_random_access &&) = default;
61  ~view_enforce_random_access() = default;
62 
64  explicit constexpr view_enforce_random_access(urng_t range) : urng{std::move(range)}
65  {}
66 
68  template <typename viewable_rng_t>
70  requires !std::same_as<remove_cvref_t<viewable_rng_t>, view_enforce_random_access> &&
71  std::ranges::viewable_range<viewable_rng_t> &&
74  explicit constexpr view_enforce_random_access(viewable_rng_t range) :
75  view_enforce_random_access{std::views::all(range)}
76  {}
78 
82  constexpr auto begin() noexcept
84  {
85  return enforced_random_access_iterator<decltype(std::ranges::begin(urng))>{std::ranges::begin(urng)};
86  }
87 
89  constexpr auto begin() const noexcept
91  requires const_iterable_range<urng_t>
93  {
94  return enforced_random_access_iterator<decltype(std::ranges::cbegin(urng))>{std::ranges::cbegin(urng)};
95  }
96 
98  constexpr auto cbegin() const noexcept
100  requires const_iterable_range<urng_t>
102  {
103  return begin();
104  }
105 
114  constexpr auto end() noexcept
115  {
116  if constexpr (std::ranges::common_range<urng_t>)
117  return enforced_random_access_iterator<decltype(std::ranges::end(urng))>{std::ranges::end(urng)};
118  else
119  return urng.end();
120  }
121 
123  constexpr auto end() const noexcept
125  requires const_iterable_range<urng_t>
127  {
128  if constexpr (std::ranges::common_range<urng_t>)
129  return enforced_random_access_iterator<decltype(std::ranges::cend(urng))>{std::ranges::cend(urng)};
130  else
131  return std::ranges::cend(urng);
132  }
133 
135  constexpr auto cend() const noexcept
137  requires const_iterable_range<urng_t>
139  {
140  return end();
141  }
143 
144  urng_t urng;
145 };
146 
155 template <std::ranges::view urng_t>
159 template <typename underlying_iter_t>
160 class view_enforce_random_access<urng_t>::enforced_random_access_iterator :
161  public inherited_iterator_base<enforced_random_access_iterator<underlying_iter_t>, underlying_iter_t>
162 {
163 private:
165  using base_t = inherited_iterator_base<enforced_random_access_iterator<underlying_iter_t>, underlying_iter_t>;
166 
167 public:
168 
170  using iterator_category = std::random_access_iterator_tag;
171 
175  // Importing base's constructors.
176  using base_t::base_t;
178  constexpr enforced_random_access_iterator() = default;
180  constexpr enforced_random_access_iterator(enforced_random_access_iterator const &) = default;
182  constexpr enforced_random_access_iterator(enforced_random_access_iterator &&) = default;
184  constexpr enforced_random_access_iterator & operator=(enforced_random_access_iterator const &) = default;
186  constexpr enforced_random_access_iterator & operator=(enforced_random_access_iterator &&) = default;
188  ~enforced_random_access_iterator() = default;
190 
195  // Importing base's equality operators
196  using base_t::operator==;
197  using base_t::operator!=;
199  friend constexpr bool operator==(enforced_random_access_iterator const & lhs,
200  std::ranges::sentinel_t<urng_t> const & rhs)
201  noexcept(noexcept(std::declval<underlying_iter_t const &>() ==
202  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
203  {
204  return static_cast<underlying_iter_t const &>(lhs) == rhs;
205  }
206 
208  friend constexpr bool operator==(std::ranges::sentinel_t<urng_t> const & lhs,
209  enforced_random_access_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  }
215 
217  friend constexpr bool operator!=(enforced_random_access_iterator const & lhs,
218  std::ranges::sentinel_t<urng_t> const & rhs)
219  noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
220  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
221  {
222  return !(lhs == rhs);
223  }
224 
226  friend constexpr bool operator!=(std::ranges::sentinel_t<urng_t> const & lhs,
227  enforced_random_access_iterator const & rhs)
228  noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
229  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
230  {
231  return rhs != lhs;
232  }
234 
238  // Import operator from base.
239  using base_t::operator-;
240 
242  constexpr typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t> const & rhs) const
243  noexcept(noexcept(std::declval<underlying_iter_t const &>() -
244  std::declval<std::ranges::sentinel_t<urng_t> const &>()))
245  requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
246  {
247  return static_cast<underlying_iter_t const &>(*this) - rhs;
248  }
249 
251  constexpr friend typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t> const & lhs,
252  enforced_random_access_iterator const & rhs)
253  noexcept(noexcept(std::declval<std::ranges::sentinel_t<urng_t> const &>() -
254  std::declval<underlying_iter_t const &>()))
255  requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
256  {
257  return lhs - static_cast<underlying_iter_t const &>(rhs);
258  }
260 };
261 
266 template <std::ranges::viewable_range rng_t>
268 view_enforce_random_access(rng_t &&) -> view_enforce_random_access<std::ranges::all_view<rng_t>>;
270 
271 // ============================================================================
272 // pseudo_random_access_fn (adaptor definition)
273 // ============================================================================
274 
276 struct pseudo_random_access_fn : public adaptor_base<pseudo_random_access_fn>
277 {
278 private:
280  using base_t = adaptor_base<pseudo_random_access_fn>;
281 
282 public:
284  using base_t::base_t;
285 
286 private:
288  friend base_t;
289 
293  template <std::ranges::viewable_range urng_t>
294  static constexpr auto impl(urng_t && urange)
295  {
296  static_assert(std::ranges::random_access_range<urng_t> || pseudo_random_access_range<urng_t>,
297  "The adapted range must either model std::ranges::random_access_range or must be "
298  "a specific SeqAn range type that supports pseudo random access.");
299  static_assert(std::ranges::forward_range<urng_t>,
300  "The underlying range must model std::ranges::forward_range.");
301 
302  if constexpr (std::ranges::random_access_range<urng_t>)
303  { // Nothing to do, just return as ref_view or original view.
304  return std::views::all(std::forward<urng_t>(urange));
305  }
306  else
307  { // Get a subrange using the random access iterators of the container.
308  return view_enforce_random_access{std::forward<urng_t>(urange)};
309  }
310  }
311 };
312 
313 } // namespace seqan3::detail
314 
315 namespace seqan3::views
316 {
317 
388 inline constexpr auto enforce_random_access = detail::pseudo_random_access_fn{};
390 } // namespace seqan3::views
seqan3::views
The SeqAn namespace for views.
Definition: view_to_simd.hpp:672
constructible_from
The std::constructible_from concept specifies that a variable of type T can be initialized with the g...
std::rel_ops::operator!=
T operator!=(T... args)
iterator
Provides C++20 additions to the <iterator> header.
std::random_access_iterator_tag
seqan3::views::move
const auto move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
concept.hpp
Additional non-standard concepts for ranges.
same_as
The concept std::same_as<T, U> is satisfied if and only if T and U denote the same type.
const_iterable_range
Specifies requirements of an input range type for which the const version of that type satisfies the ...
seqan3::views::enforce_random_access
constexpr auto enforce_random_access
A view adaptor that converts a pseudo random access range to a std::random_access_range.
Definition: enforce_random_access.hpp:388
pseudo_random_access_range
This concept checks if a type models a pseudo random access range.
seqan3::search_cfg::all
constexpr detail::search_mode_all all
Configuration element to receive all hits within the error bounds.
Definition: mode.hpp:43
ranges
Adaptations of concepts from the Ranges TS.
std::begin
T begin(T... args)
std
SeqAn specific customisations in the standard namespace.
std::end
T end(T... args)
inherited_iterator_base.hpp
Provides the seqan3::detail::inherited_iterator_base template.
detail.hpp
Auxiliary header for the views submodule .
std::declval
T declval(T... args)