SeqAn3 3.3.0-rc.1
The Modern C++ library for sequence analysis.
enforce_random_access.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, 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 <iterator>
16#include <ranges>
17#include <type_traits>
18
22
23namespace seqan3::detail
24{
25
26// ============================================================================
27// view_pseudo_random_access
28// ============================================================================
29
41template <std::ranges::view urng_t>
43class view_enforce_random_access : public std::ranges::view_interface<view_enforce_random_access<urng_t>>
44{
45private:
46 // Iterator declaration.
47 template <typename underlying_iter_t>
48 class basic_iterator;
49
50public:
54 constexpr view_enforce_random_access() = default;
60
62 explicit constexpr view_enforce_random_access(urng_t && range) : urng{std::move(range)}
63 {}
64
66 template <typename viewable_rng_t>
67 requires (!std::same_as<std::remove_cvref_t<viewable_rng_t>, view_enforce_random_access>)
68 && std::ranges::viewable_range<viewable_rng_t>
69 && std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<viewable_rng_t>>>
70 explicit constexpr view_enforce_random_access(viewable_rng_t && range) :
71 view_enforce_random_access{std::views::all(std::forward<viewable_rng_t>(range))}
72 {}
74
79 constexpr auto begin() noexcept
80 {
82 }
83
85 constexpr auto begin() const noexcept
86 requires const_iterable_range<urng_t>
87 {
89 }
90
99 constexpr auto end() noexcept
100 {
101 if constexpr (std::ranges::common_range<urng_t>)
102 return basic_iterator<decltype(std::ranges::end(urng))>{std::ranges::end(urng)};
103 else
104 return urng.end();
105 }
106
108 constexpr auto end() const noexcept
109 requires const_iterable_range<urng_t>
110 {
111 if constexpr (std::ranges::common_range<urng_t>)
112 return basic_iterator<decltype(std::ranges::cend(urng))>{std::ranges::cend(urng)};
113 else
114 return std::ranges::cend(urng);
115 }
117
118 urng_t urng;
119};
120
129template <std::ranges::view urng_t>
131template <typename underlying_iter_t>
133 public inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>
134{
135private:
138
139public:
144
148 // Importing base's constructors.
149 using base_t::base_t;
151 constexpr basic_iterator() = default;
153 constexpr basic_iterator(basic_iterator const &) = default;
155 constexpr basic_iterator(basic_iterator &&) = default;
157 constexpr basic_iterator & operator=(basic_iterator const &) = default;
159 constexpr basic_iterator & operator=(basic_iterator &&) = default;
161 ~basic_iterator() = default;
163
168 // Importing base's equality operators
169 using base_t::operator==;
170 using base_t::operator!=;
172 friend constexpr bool operator==(basic_iterator const & lhs, std::ranges::sentinel_t<urng_t> const & rhs) noexcept(
173 noexcept(std::declval<underlying_iter_t const &>() == std::declval<std::ranges::sentinel_t<urng_t> const &>()))
174 {
175 return lhs.base() == rhs;
176 }
177
179 friend constexpr bool operator==(std::ranges::sentinel_t<urng_t> const & lhs, basic_iterator const & rhs) noexcept(
180 noexcept(std::declval<underlying_iter_t const &>() == std::declval<std::ranges::sentinel_t<urng_t> const &>()))
181 {
182 return rhs == lhs;
183 }
184
186 friend constexpr bool operator!=(basic_iterator const & lhs, std::ranges::sentinel_t<urng_t> const & rhs) noexcept(
187 noexcept(std::declval<underlying_iter_t const &>() != std::declval<std::ranges::sentinel_t<urng_t> const &>()))
188 {
189 return !(lhs == rhs);
190 }
191
193 friend constexpr bool operator!=(std::ranges::sentinel_t<urng_t> const & lhs, basic_iterator const & rhs) noexcept(
194 noexcept(std::declval<underlying_iter_t const &>() != std::declval<std::ranges::sentinel_t<urng_t> const &>()))
195 {
196 return rhs != lhs;
197 }
199
203 // Import operator from base.
204 using base_t::operator-;
205
207 constexpr typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t> const & rhs) const
208 noexcept(noexcept(std::declval<underlying_iter_t const &>()
209 - std::declval<std::ranges::sentinel_t<urng_t> const &>()))
210 requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
211 {
212 return this->base() - rhs;
213 }
214
216 constexpr friend typename base_t::difference_type
217 operator-(std::ranges::sentinel_t<urng_t> const & lhs,
218 basic_iterator const & rhs) noexcept(noexcept(std::declval<std::ranges::sentinel_t<urng_t> const &>()
219 - std::declval<underlying_iter_t const &>()))
220 requires std::sized_sentinel_for<std::ranges::sentinel_t<urng_t>, underlying_iter_t>
221 {
222 return lhs - rhs.base();
223 }
225};
226
232template <std::ranges::viewable_range rng_t>
235
236// ============================================================================
237// pseudo_random_access_fn (adaptor definition)
238// ============================================================================
239
241struct pseudo_random_access_fn : public adaptor_base<pseudo_random_access_fn>
242{
243private:
246
247public:
249 using base_t::base_t;
250
251private:
253 friend base_t;
254
258 template <std::ranges::viewable_range urng_t>
259 static constexpr auto impl(urng_t && urange)
260 {
261 static_assert(std::ranges::random_access_range<urng_t> || pseudo_random_access_range<urng_t>,
262 "The adapted range must either model std::ranges::random_access_range or must be "
263 "a specific SeqAn range type that supports pseudo random access.");
264 static_assert(std::ranges::forward_range<urng_t>,
265 "The underlying range must model std::ranges::forward_range.");
266
267 if constexpr (std::ranges::random_access_range<urng_t>)
268 { // Nothing to do, just return as ref_view or original view.
269 return std::views::all(std::forward<urng_t>(urange));
270 }
271 else
272 { // Get a subrange using the random access iterators of the container.
273 return view_enforce_random_access{std::forward<urng_t>(urange)};
274 }
275 }
276};
277
278} // namespace seqan3::detail
279
280namespace seqan3::views
281{
351
352} // namespace seqan3::views
Provides seqan3::detail::adaptor_base and seqan3::detail::combined_adaptor.
T begin(T... args)
CRTP-base to simplify the definition of range adaptor closure objects and similar types.
Definition: adaptor_base.hpp:77
A CRTP base template for creating iterators that inherit from other iterators.
Definition: inherited_iterator_base.hpp:52
constexpr base_t const & base() const &noexcept
Get a const reference to the base.
Definition: inherited_iterator_base.hpp:109
Iterator wrapper for the underlying range iterator enforcing std::random_access_iterator_tag.
Definition: enforce_random_access.hpp:134
friend constexpr bool operator!=(basic_iterator const &lhs, std::ranges::sentinel_t< urng_t > const &rhs) noexcept(noexcept(std::declval< underlying_iter_t const & >() !=std::declval< std::ranges::sentinel_t< urng_t > const & >()))
Tests if iterator is not at the end.
Definition: enforce_random_access.hpp:186
constexpr basic_iterator & operator=(basic_iterator &&)=default
Defaulted.
constexpr basic_iterator(basic_iterator const &)=default
Defaulted.
constexpr basic_iterator(basic_iterator &&)=default
Defaulted.
constexpr friend base_t::difference_type operator-(std::ranges::sentinel_t< urng_t > const &lhs, basic_iterator const &rhs) noexcept(noexcept(std::declval< std::ranges::sentinel_t< urng_t > const & >() - std::declval< underlying_iter_t const & >()))
Computes the distance betwen this iterator and the sentinel of the underlying range.
Definition: enforce_random_access.hpp:217
friend constexpr bool operator==(basic_iterator const &lhs, std::ranges::sentinel_t< urng_t > const &rhs) noexcept(noexcept(std::declval< underlying_iter_t const & >()==std::declval< std::ranges::sentinel_t< urng_t > const & >()))
Tests if iterator is at the end.
Definition: enforce_random_access.hpp:172
constexpr basic_iterator & operator=(basic_iterator const &)=default
Defaulted.
friend constexpr bool operator!=(std::ranges::sentinel_t< urng_t > const &lhs, basic_iterator const &rhs) noexcept(noexcept(std::declval< underlying_iter_t const & >() !=std::declval< std::ranges::sentinel_t< urng_t > const & >()))
Tests if iterator is not at the end.
Definition: enforce_random_access.hpp:193
friend constexpr bool operator==(std::ranges::sentinel_t< urng_t > const &lhs, basic_iterator const &rhs) noexcept(noexcept(std::declval< underlying_iter_t const & >()==std::declval< std::ranges::sentinel_t< urng_t > const & >()))
Tests if iterator is at the end.
Definition: enforce_random_access.hpp:179
constexpr base_t::difference_type operator-(std::ranges::sentinel_t< urng_t > const &rhs) const noexcept(noexcept(std::declval< underlying_iter_t const & >() - std::declval< std::ranges::sentinel_t< urng_t > const & >()))
Computes the distance betwen this iterator and the sentinel of the underlying range.
Definition: enforce_random_access.hpp:207
View to force random access range iterator for seqan3::pseudo_random_access_range.
Definition: enforce_random_access.hpp:44
constexpr view_enforce_random_access & operator=(view_enforce_random_access const &)=default
Defaulted.
constexpr auto end() noexcept
Returns the sentinel to the end of the range.
Definition: enforce_random_access.hpp:99
view_enforce_random_access(rng_t &&) -> view_enforce_random_access< std::views::all_t< rng_t > >
A deduction guide for the view class template.
constexpr view_enforce_random_access(view_enforce_random_access &&)=default
Defaulted.
constexpr auto end() const noexcept
Returns the sentinel to the end of the range.
Definition: enforce_random_access.hpp:108
constexpr view_enforce_random_access()=default
Defaulted.
constexpr view_enforce_random_access(viewable_rng_t &&range)
Construction from the underlying viewable range.
Definition: enforce_random_access.hpp:70
urng_t urng
The underlying range.
Definition: enforce_random_access.hpp:118
constexpr auto begin() const noexcept
Returns the iterator to the begin of the range.
Definition: enforce_random_access.hpp:85
constexpr view_enforce_random_access(urng_t &&range)
Construction from the underlying view.
Definition: enforce_random_access.hpp:62
constexpr view_enforce_random_access & operator=(view_enforce_random_access &&)=default
Defaulted.
constexpr auto begin() noexcept
Returns the iterator to the begin of the range.
Definition: enforce_random_access.hpp:79
constexpr view_enforce_random_access(view_enforce_random_access const &)=default
Defaulted.
constexpr auto all
Returns a view that includes all elements of the range argument.
Definition: all_view.hpp:204
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:350
Provides the seqan3::detail::inherited_iterator_base template.
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.
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
The SeqAn namespace for views.
Definition: char_strictly_to.hpp:22
SeqAn specific customisations in the standard namespace.
View adaptor definition for seqan3::views::enforce_random_access.
Definition: enforce_random_access.hpp:242
static constexpr auto impl(urng_t &&urange)
Call the view's constructor with the underlying view as argument.
Definition: enforce_random_access.hpp:259
friend base_t
Befriend the base class so it can call impl().
Definition: enforce_random_access.hpp:253
Additional non-standard concepts for ranges.