21 namespace seqan3::detail
39 template <std::ranges::view urng_t>
43 class view_enforce_random_access :
public ranges::view_interface<view_enforce_random_access<urng_t>>
48 template <
typename underlying_iter_t>
49 class enforced_random_access_iterator;
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> &&
74 explicit constexpr view_enforce_random_access(viewable_rng_t range) :
82 constexpr
auto begin() noexcept
85 return enforced_random_access_iterator<decltype(std::ranges::begin(urng))>{
std::ranges::begin(urng)};
89 constexpr
auto begin() const noexcept
94 return enforced_random_access_iterator<decltype(std::ranges::cbegin(urng))>{
std::ranges::cbegin(urng)};
98 constexpr
auto cbegin() const noexcept
114 constexpr
auto end() noexcept
116 if constexpr (std::ranges::common_range<urng_t>)
117 return enforced_random_access_iterator<decltype(std::ranges::end(urng))>{std::ranges::end(urng)};
123 constexpr
auto end() const noexcept
128 if constexpr (std::ranges::common_range<urng_t>)
129 return enforced_random_access_iterator<decltype(std::ranges::cend(urng))>{std::ranges::cend(urng)};
131 return std::ranges::cend(urng);
135 constexpr
auto cend() const noexcept
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>
165 using base_t = inherited_iterator_base<enforced_random_access_iterator<underlying_iter_t>, underlying_iter_t>;
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;
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 &>()))
204 return static_cast<underlying_iter_t const &>(lhs) == rhs;
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 &>()))
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 &>()))
222 return !(lhs == rhs);
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 &>()))
239 using base_t::operator-;
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>
247 return static_cast<underlying_iter_t const &>(*
this) - rhs;
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>
257 return lhs - static_cast<underlying_iter_t const &>(rhs);
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>>;
276 struct pseudo_random_access_fn :
public adaptor_base<pseudo_random_access_fn>
280 using base_t = adaptor_base<pseudo_random_access_fn>;
284 using base_t::base_t;
293 template <std::ranges::viewable_range urng_t>
294 static constexpr
auto impl(urng_t && urange)
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.");
302 if constexpr (std::ranges::random_access_range<urng_t>)
308 return view_enforce_random_access{std::forward<urng_t>(urange)};