SeqAn3 3.1.0
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>
18
22
23namespace seqan3::detail
24{
25
26// ============================================================================
27// view_pseudo_random_access
28// ============================================================================
29
41template <std::ranges::view urng_t>
45class view_enforce_random_access : public std::ranges::view_interface<view_enforce_random_access<urng_t>>
46{
47private:
48
49 // Iterator declaration.
50 template <typename underlying_iter_t>
51 class basic_iterator;
52
53public:
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
139template <std::ranges::view urng_t>
143template <typename underlying_iter_t>
144class view_enforce_random_access<urng_t>::basic_iterator :
145 public inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>
146{
147private:
149 using base_t = inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>;
150
151public:
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
249template <std::ranges::viewable_range rng_t>
250view_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
258struct pseudo_random_access_fn : public adaptor_base<pseudo_random_access_fn>
259{
260private:
262 using base_t = adaptor_base<pseudo_random_access_fn>;
263
264public:
266 using base_t::base_t;
267
268private:
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
297namespace seqan3::views
298{
367inline constexpr auto enforce_random_access = detail::pseudo_random_access_fn{};
368
369} // namespace seqan3::views
Provides seqan3::detail::adaptor_base and seqan3::detail::combined_adaptor.
T begin(T... args)
T end(T... args)
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:367
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 <iterator> header from C++20's standard library.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
The <ranges> header from C++20's standard library.
The <type_traits> header from C++20's standard library.
Additional non-standard concepts for ranges.