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#if !SEQAN3_WORKAROUND_FURTHER_CONSTRAIN_FRIEND_DECLARATION
279 friend class basic_iterator;
282 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
298 using reference = common_tuple<underlying_ref_t, underlying_ref_t>;
300 using pointer = void;
302 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
308 basic_iterator() =
default;
309 basic_iterator(basic_iterator
const &) =
default;
310 basic_iterator(basic_iterator &&) =
default;
311 basic_iterator & operator=(basic_iterator
const &) =
default;
312 basic_iterator & operator=(basic_iterator &&) =
default;
313 ~basic_iterator() =
default;
327 constexpr basic_iterator(underlying_iterator_type iter,
328 underlying_iterator_type begin_it,
329 underlying_iterator_type end_it) noexcept :
331 second_it{std::ranges::next(iter, 1, end_it)},
344 template <
typename other_range_type>
346 requires std::convertible_to<other_range_type, range_type &> &&
349 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
350 basic_iterator{std::move(other.first_it), std::move(other.begin_it), std::move(other.end_it)}
358 constexpr reference operator*() const
359 noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
361 return reference{*first_it, *second_it};
367 constexpr reference operator[](
size_t const index)
const
368 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
370 requires std::random_access_iterator<underlying_iterator_type>
373 return *(*
this + index);
381 constexpr basic_iterator & operator++()
382 noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
384 if (++second_it == end_it)
387 second_it = first_it;
394 constexpr basic_iterator operator++(
int )
395 noexcept(
noexcept(std::declval<underlying_iterator_type &>()++))
397 basic_iterator tmp{*
this};
403 constexpr basic_iterator & operator--()
404 noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
406 requires
std::bidirectional_iterator<underlying_iterator_type>
409 if (--second_it == first_it)
419 constexpr basic_iterator operator--(
int )
420 noexcept(
noexcept(std::declval<underlying_iterator_type &>()--))
422 requires std::bidirectional_iterator<underlying_iterator_type>
425 basic_iterator tmp{*
this};
432 constexpr basic_iterator & operator+=(difference_type
const offset)
433 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
435 requires std::random_access_iterator<underlying_iterator_type>
438 from_index(to_index() + offset);
444 constexpr basic_iterator operator+(difference_type
const offset)
const
445 noexcept(
noexcept(std::declval<basic_iterator &>() += 1))
447 requires std::random_access_iterator<underlying_iterator_type>
450 basic_iterator tmp{*
this};
451 return (tmp += offset);
456 constexpr friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
457 noexcept(
noexcept(std::declval<basic_iterator<range_type> &>().from_index(1)))
459 requires std::random_access_iterator<underlying_iterator_type>
462 iter.from_index(iter.to_index() +
offset);
468 constexpr basic_iterator & operator-=(difference_type
const offset)
469 noexcept(
noexcept(std::declval<basic_iterator &>().from_index(1)))
471 requires std::random_access_iterator<underlying_iterator_type>
474 from_index(to_index() - offset);
480 constexpr basic_iterator operator-(difference_type
const offset)
const
481 noexcept(
noexcept(std::declval<basic_iterator &>() -= 1))
483 requires std::random_access_iterator<underlying_iterator_type>
486 basic_iterator tmp{*
this};
487 return (tmp -= offset);
492 template <
typename other_range_type>
494 requires std::random_access_iterator<underlying_iterator_type> &&
497 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
498 noexcept(
noexcept(std::declval<basic_iterator &>().to_index()))
500 return static_cast<difference_type
>(to_index() - rhs.to_index());
514 template <
typename other_range_type>
516 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
519 constexpr bool operator==(basic_iterator<other_range_type>
const & rhs)
const
520 noexcept(
noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
522 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
526 template <
typename other_range_type>
528 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
531 constexpr bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
532 noexcept(
noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
534 return !(*
this == rhs);
538 template <
typename other_range_type>
540 requires std::totally_ordered_with<underlying_iterator_type,
541 std::ranges::iterator_t<other_range_type>> &&
544 constexpr bool operator<(basic_iterator<other_range_type>
const & rhs)
const
545 noexcept(
noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
547 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
551 template <
typename other_range_type>
553 requires std::totally_ordered_with<underlying_iterator_type,
554 std::ranges::iterator_t<other_range_type>> &&
557 constexpr bool operator>(basic_iterator<other_range_type>
const & rhs)
const
558 noexcept(
noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
561 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
565 template <
typename other_range_type>
567 requires std::totally_ordered_with<underlying_iterator_type,
568 std::ranges::iterator_t<other_range_type>> &&
571 constexpr bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
572 noexcept(
noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
574 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
578 template <
typename other_range_type>
580 requires std::totally_ordered_with<underlying_iterator_type,
581 std::ranges::iterator_t<other_range_type>> &&
584 constexpr bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
585 noexcept(
noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
587 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
605 constexpr size_t to_index() const
606 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
608 requires
std::random_access_iterator<underlying_iterator_type>
611 size_t src_size = end_it - begin_it;
612 size_t index_i = first_it - begin_it;
613 size_t index_j = second_it - begin_it;
614 return (src_size * (src_size - 1)/2) - (src_size - index_i) * ((src_size - index_i) - 1)/2 +
615 index_j - index_i - 1;
622 constexpr void from_index(
size_t const index)
623 noexcept(
noexcept(std::declval<underlying_iterator_type &>() - std::declval<underlying_iterator_type &>()) &&
624 noexcept(std::declval<underlying_iterator_type &>() + 1))
626 requires std::random_access_iterator<underlying_iterator_type>
629 size_t src_size = end_it - begin_it;
630 size_t index_i = src_size - 2 -
632 size_t index_j = index + index_i + 1 - src_size * (src_size - 1)/2 + (src_size - index_i) *
633 ((src_size - index_i) - 1)/2;
634 first_it = begin_it + index_i;
635 second_it = begin_it + index_j;
639 underlying_iterator_type first_it{};
641 underlying_iterator_type second_it{};
643 underlying_iterator_type begin_it{};
645 underlying_iterator_type end_it{};
714inline 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:714
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_strictly_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.