24namespace seqan3::detail
41template <std::ranges::view underlying_range_type>
43 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
45class pairwise_combine_view :
public std::ranges::view_interface<pairwise_combine_view<underlying_range_type>>
50 template <
typename range_type>
58 using iterator = basic_iterator<underlying_range_type>;
60 using const_iterator = transformation_trait_or_t<std::type_identity<basic_iterator<underlying_range_type const>>,
68 pairwise_combine_view() =
default;
69 pairwise_combine_view(pairwise_combine_view
const &) =
default;
70 pairwise_combine_view(pairwise_combine_view &&) =
default;
71 pairwise_combine_view & operator=(pairwise_combine_view
const &) =
default;
72 pairwise_combine_view & operator=(pairwise_combine_view &&) =
default;
73 ~pairwise_combine_view() =
default;
91 explicit constexpr pairwise_combine_view(underlying_range_type range) : u_range{
std::move(range)}
94 if (std::ranges::empty(u_range))
96 back_iterator = std::ranges::end(u_range);
100 if constexpr (std::ranges::bidirectional_range<underlying_range_type>)
102 back_iterator = std::ranges::prev(std::ranges::end(u_range));
107 if constexpr (std::ranges::sized_range<underlying_range_type>)
113 auto tmp_it = back_iterator;
116 back_iterator = tmp_it;
117 }
while (++tmp_it != std::ranges::end(u_range));
142 template <
typename other_range_t>
144 requires (!std::same_as<std::remove_cvref_t<other_range_t>, pairwise_combine_view>) &&
145 std::ranges::viewable_range<other_range_t> &&
146 std::constructible_from<underlying_range_type,
152 explicit constexpr pairwise_combine_view(other_range_t && range) :
153 pairwise_combine_view{std::views::all(std::forward<other_range_t>(range))}
172 constexpr iterator
begin() noexcept
178 constexpr const_iterator
begin() const noexcept
199 constexpr iterator
end() noexcept
205 constexpr const_iterator
end() const noexcept
218#if SEQAN3_WORKAROUND_GCC_NON_TEMPLATE_REQUIRES
219 template <
typename = underlying_range_type>
221 constexpr auto size() const noexcept
223 requires
std::ranges::sized_range<underlying_range_type>
234 underlying_range_type u_range{};
236 std::ranges::iterator_t<underlying_range_type> back_iterator{};
244template <std::ranges::viewable_range other_range_t>
245pairwise_combine_view(other_range_t && range) ->
246 pairwise_combine_view<std::views::all_t<other_range_t>>;
262template <std::ranges::view underlying_range_type>
264 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
266template <
typename range_type>
267class pairwise_combine_view<underlying_range_type>::basic_iterator
268 :
public maybe_iterator_category<std::ranges::iterator_t<range_type>>
273 template <
typename other_range_type>
275 friend class basic_iterator;
278 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
294 using reference = common_tuple<underlying_ref_t, underlying_ref_t>;
296 using pointer = void;
298 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
304 basic_iterator() =
default;
305 basic_iterator(basic_iterator
const &) =
default;
306 basic_iterator(basic_iterator &&) =
default;
307 basic_iterator & operator=(basic_iterator
const &) =
default;
308 basic_iterator & operator=(basic_iterator &&) =
default;
309 ~basic_iterator() =
default;
323 constexpr basic_iterator(underlying_iterator_type iter,
324 underlying_iterator_type begin_it,
325 underlying_iterator_type end_it) noexcept :
327 second_it{std::ranges::next(iter, 1, end_it)},
340 template <
typename other_range_type>
342 requires std::convertible_to<other_range_type, range_type &> &&
345 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
346 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
354 constexpr reference operator*() const
355 noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
357 return reference{*first_it, *second_it};
363 constexpr reference operator[](
size_t const index)
const
364 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
366 requires std::random_access_iterator<underlying_iterator_type>
369 return *(*
this + index);
377 constexpr basic_iterator & operator++()
378 noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
380 if (++second_it == end_it)
383 second_it = first_it;
390 constexpr basic_iterator operator++(
int )
391 noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
393 basic_iterator tmp{*
this};
399 constexpr basic_iterator & operator--()
400 noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
402 requires
std::bidirectional_iterator<underlying_iterator_type>
405 if (--second_it == first_it)
415 constexpr basic_iterator operator--(
int )
416 noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
418 requires std::bidirectional_iterator<underlying_iterator_type>
421 basic_iterator tmp{*
this};
428 constexpr basic_iterator & operator+=(difference_type
const offset)
429 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
431 requires std::random_access_iterator<underlying_iterator_type>
434 from_index(to_index() + offset);
440 constexpr basic_iterator operator+(difference_type
const offset)
const
441 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
443 requires std::random_access_iterator<underlying_iterator_type>
446 basic_iterator tmp{*
this};
447 return (tmp += offset);
452 constexpr friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
453 noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
455 requires std::random_access_iterator<underlying_iterator_type>
458 iter.from_index(iter.to_index() +
offset);
464 constexpr basic_iterator & operator-=(difference_type
const offset)
465 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
467 requires std::random_access_iterator<underlying_iterator_type>
470 from_index(to_index() - offset);
476 constexpr basic_iterator operator-(difference_type
const offset)
const
477 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
479 requires std::random_access_iterator<underlying_iterator_type>
482 basic_iterator tmp{*
this};
483 return (tmp -= offset);
488 template <
typename other_range_type>
490 requires std::random_access_iterator<underlying_iterator_type> &&
493 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
494 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
496 return static_cast<difference_type
>(to_index() - rhs.to_index());
510 template <
typename other_range_type>
512 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
515 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
516 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
518 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
522 template <
typename other_range_type>
524 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
527 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
528 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
530 return !(*
this == rhs);
534 template <
typename other_range_type>
536 requires std::totally_ordered_with<underlying_iterator_type,
537 std::ranges::iterator_t<other_range_type>> &&
540 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
541 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
543 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
547 template <
typename other_range_type>
549 requires std::totally_ordered_with<underlying_iterator_type,
550 std::ranges::iterator_t<other_range_type>> &&
553 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
554 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
557 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
561 template <
typename other_range_type>
563 requires std::totally_ordered_with<underlying_iterator_type,
564 std::ranges::iterator_t<other_range_type>> &&
567 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
568 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
570 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
574 template <
typename other_range_type>
576 requires std::totally_ordered_with<underlying_iterator_type,
577 std::ranges::iterator_t<other_range_type>> &&
580 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
581 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
583 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
601 constexpr size_t to_index() const
602 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
604 requires
std::random_access_iterator<underlying_iterator_type>
607 size_t src_size = end_it - begin_it;
608 size_t index_i = first_it - begin_it;
609 size_t index_j = second_it - begin_it;
610 return (src_size * (src_size - 1)/2) - (src_size - index_i) * ((src_size - index_i) - 1)/2 +
611 index_j - index_i - 1;
618 constexpr void from_index(
size_t const index)
619 noexcept(
noexcept(std::declval<underlying_iterator_type &>() - std::declval<underlying_iterator_type &>()) &&
620 noexcept(std::declval<underlying_iterator_type &>() + 1))
622 requires std::random_access_iterator<underlying_iterator_type>
625 size_t src_size = end_it - begin_it;
626 size_t index_i = src_size - 2 -
628 size_t index_j = index + index_i + 1 - src_size * (src_size - 1)/2 + (src_size - index_i) *
629 ((src_size - index_i) - 1)/2;
630 first_it = begin_it + index_i;
631 second_it = begin_it + index_j;
635 underlying_iterator_type first_it{};
637 underlying_iterator_type second_it{};
639 underlying_iterator_type begin_it{};
641 underlying_iterator_type end_it{};
710inline constexpr auto pairwise_combine = detail::adaptor_for_view_without_args<detail::pairwise_combine_view>{};
Provides seqan3::detail::adaptor_for_view_without_args.
Provides seqan3::common_tuple and seqan3::common_pair.
@ offset
Sequence (seqan3::field::seq) relative start position (0-based), unsigned value.
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:151
constexpr auto pairwise_combine
A view adaptor that generates all pairwise combinations of the elements of the underlying range.
Definition: pairwise_combine.hpp:710
Specifies requirements of an input range type for which the const version of that type satisfies the ...
Provides various transformation traits for use on iterators.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
The <ranges> header from C++20's standard library.
Additional non-standard concepts for ranges.