21 namespace seqan3::detail
39 template <std::ranges::view urng_t>
43 class view_enforce_random_access :
public std::ranges::view_interface<view_enforce_random_access<urng_t>>
48 template <
typename underlying_iter_t>
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;
64 explicit constexpr view_enforce_random_access(urng_t range) : urng{
std::move(range)}
68 template <
typename viewable_rng_t>
71 std::ranges::viewable_range<viewable_rng_t> &&
72 std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<viewable_rng_t>>>
74 explicit constexpr view_enforce_random_access(viewable_rng_t range) :
75 view_enforce_random_access{std::views::all(range)}
82 constexpr
auto begin() noexcept
89 constexpr
auto begin() const noexcept
105 constexpr
auto end() noexcept
107 if constexpr (std::ranges::common_range<urng_t>)
108 return basic_iterator<decltype(std::ranges::end(urng))>{std::ranges::end(urng)};
114 constexpr
auto end() const noexcept
119 if constexpr (std::ranges::common_range<urng_t>)
120 return basic_iterator<decltype(std::ranges::cend(urng))>{std::ranges::cend(urng)};
122 return std::ranges::cend(urng);
137 template <std::ranges::view urng_t>
141 template <
typename underlying_iter_t>
142 class view_enforce_random_access<urng_t>::basic_iterator :
143 public inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>
147 using base_t = inherited_iterator_base<basic_iterator<underlying_iter_t>, underlying_iter_t>;
154 using iterator_concept = iterator_category;
160 using base_t::base_t;
162 constexpr basic_iterator() =
default;
164 constexpr basic_iterator(basic_iterator
const &) =
default;
166 constexpr basic_iterator(basic_iterator &&) =
default;
168 constexpr basic_iterator & operator=(basic_iterator
const &) =
default;
170 constexpr basic_iterator & operator=(basic_iterator &&) =
default;
172 ~basic_iterator() =
default;
180 using base_t::operator==;
181 using base_t::operator!=;
183 friend constexpr
bool operator==(basic_iterator
const & lhs, std::ranges::sentinel_t<urng_t>
const & rhs)
184 noexcept(noexcept(std::declval<underlying_iter_t const &>() ==
185 std::declval<std::ranges::sentinel_t<urng_t>
const &>()))
187 return static_cast<underlying_iter_t
const &
>(lhs) == rhs;
191 friend constexpr
bool operator==(std::ranges::sentinel_t<urng_t>
const & lhs, basic_iterator
const & rhs)
192 noexcept(noexcept(std::declval<underlying_iter_t const &>() ==
193 std::declval<std::ranges::sentinel_t<urng_t>
const &>()))
199 friend constexpr
bool operator!=(basic_iterator
const & lhs, std::ranges::sentinel_t<urng_t>
const & rhs)
200 noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
201 std::declval<std::ranges::sentinel_t<urng_t>
const &>()))
203 return !(lhs == rhs);
207 friend constexpr
bool operator!=(std::ranges::sentinel_t<urng_t>
const & lhs, basic_iterator
const & rhs)
208 noexcept(noexcept(std::declval<underlying_iter_t const &>() !=
209 std::declval<std::ranges::sentinel_t<urng_t>
const &>()))
219 using base_t::operator-;
222 constexpr
typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t>
const & rhs)
const
223 noexcept(noexcept(std::declval<underlying_iter_t const &>() -
224 std::declval<std::ranges::sentinel_t<urng_t>
const &>()))
225 requires
std::sized_sentinel_for<
std::ranges::sentinel_t<urng_t>, underlying_iter_t>
227 return static_cast<underlying_iter_t
const &
>(*this) - rhs;
231 constexpr
friend typename base_t::difference_type operator-(std::ranges::sentinel_t<urng_t>
const & lhs,
232 basic_iterator
const & rhs)
233 noexcept(noexcept(
std::declval<std::ranges::sentinel_t<urng_t>
const &>() -
234 std::declval<underlying_iter_t const &>()))
235 requires
std::sized_sentinel_for<
std::ranges::sentinel_t<urng_t>, underlying_iter_t>
237 return lhs -
static_cast<underlying_iter_t
const &
>(rhs);
246 template <std::ranges::viewable_range rng_t>
248 view_enforce_random_access(rng_t &&) -> view_enforce_random_access<std::views::all_t<rng_t>>;
256 struct pseudo_random_access_fn :
public adaptor_base<pseudo_random_access_fn>
260 using base_t = adaptor_base<pseudo_random_access_fn>;
264 using base_t::base_t;
273 template <std::ranges::viewable_range urng_t>
274 static constexpr
auto impl(urng_t && urange)
277 "The adapted range must either model std::ranges::random_access_range or must be "
278 "a specific SeqAn range type that supports pseudo random access.");
279 static_assert(std::ranges::forward_range<urng_t>,
280 "The underlying range must model std::ranges::forward_range.");
282 if constexpr (std::ranges::random_access_range<urng_t>)
284 return std::views::all(std::forward<urng_t>(urange));
288 return view_enforce_random_access{std::forward<urng_t>(urange)};