23 namespace seqan3::detail
40 template <std::ranges::view underlying_range_type>
42 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
44 class pairwise_combine_view :
public std::ranges::view_interface<pairwise_combine_view<underlying_range_type>>
49 template <
typename range_type>
57 using iterator = basic_iterator<underlying_range_type>;
59 using const_iterator = transformation_trait_or_t<std::type_identity<basic_iterator<underlying_range_type const>>,
67 pairwise_combine_view() =
default;
68 pairwise_combine_view(pairwise_combine_view
const &) =
default;
69 pairwise_combine_view(pairwise_combine_view &&) =
default;
70 pairwise_combine_view & operator=(pairwise_combine_view
const &) =
default;
71 pairwise_combine_view & operator=(pairwise_combine_view &&) =
default;
72 ~pairwise_combine_view() =
default;
90 explicit constexpr pairwise_combine_view(underlying_range_type range) : u_range{
std::
move(range)}
93 if (std::ranges::empty(u_range))
95 back_iterator = std::ranges::end(u_range);
99 if constexpr (std::ranges::bidirectional_range<underlying_range_type>)
101 back_iterator = std::ranges::prev(std::ranges::end(u_range));
106 if constexpr (std::ranges::sized_range<underlying_range_type>)
112 auto tmp_it = back_iterator;
115 back_iterator = tmp_it;
116 }
while (++tmp_it != std::ranges::end(u_range));
141 template <
typename other_range_t>
144 std::ranges::viewable_range<other_range_t> &&
145 std::constructible_from<underlying_range_type,
146 std::ranges::ref_view<std::remove_reference_t<other_range_t>>>
151 explicit constexpr pairwise_combine_view(other_range_t && range) :
152 pairwise_combine_view{
std::views::all(
std::
forward<other_range_t>(range))}
171 constexpr iterator
begin() noexcept
177 constexpr const_iterator
begin() const noexcept
198 constexpr iterator
end() noexcept
204 constexpr const_iterator
end() const noexcept
217 constexpr
auto size() const noexcept
219 requires
std::ranges::sized_range<underlying_range_type>
230 underlying_range_type u_range{};
232 std::ranges::iterator_t<underlying_range_type> back_iterator{};
240 template <std::ranges::viewable_range other_range_t>
241 pairwise_combine_view(other_range_t && range) ->
242 pairwise_combine_view<std::views::all_t<other_range_t>>;
258 template <std::ranges::view underlying_range_type>
260 requires std::ranges::forward_range<underlying_range_type> && std::ranges::common_range<underlying_range_type>
262 template <
typename range_type>
263 class pairwise_combine_view<underlying_range_type>::basic_iterator
268 template <
typename other_range_type>
270 friend class basic_iterator;
273 using underlying_iterator_type = std::ranges::iterator_t<range_type>;
289 using reference = common_tuple<underlying_ref_t, underlying_ref_t>;
291 using pointer = void;
293 using iterator_category = detail::iterator_category_tag_t<underlying_iterator_type>;
295 using iterator_concept = detail::iterator_concept_tag_t<underlying_iterator_type>;
301 basic_iterator() =
default;
302 basic_iterator(basic_iterator
const &) =
default;
303 basic_iterator(basic_iterator &&) =
default;
304 basic_iterator & operator=(basic_iterator
const &) =
default;
305 basic_iterator & operator=(basic_iterator &&) =
default;
306 ~basic_iterator() =
default;
320 constexpr basic_iterator(underlying_iterator_type iter,
321 underlying_iterator_type begin_it,
322 underlying_iterator_type end_it) noexcept :
324 second_it{std::ranges::next(iter, 1, end_it)},
337 template <
typename other_range_type>
339 requires std::convertible_to<other_range_type, range_type &> &&
342 constexpr basic_iterator(basic_iterator<other_range_type> other) noexcept :
351 constexpr reference operator*() const
352 noexcept(noexcept(*
std::declval<underlying_iterator_type>()))
354 return reference{*first_it, *second_it};
360 constexpr reference operator[](
size_t const index)
const
361 noexcept(noexcept(std::declval<basic_iterator &>().from_index(1)))
363 requires
std::random_access_iterator<underlying_iterator_type>
366 return *(*
this + index);
374 constexpr basic_iterator & operator++()
375 noexcept(noexcept(++
std::declval<underlying_iterator_type &>()))
377 if (++second_it == end_it)
380 second_it = first_it;
387 constexpr basic_iterator operator++(
int )
388 noexcept(noexcept(std::declval<underlying_iterator_type &>()++))
390 basic_iterator tmp{*
this};
396 constexpr basic_iterator & operator--()
397 noexcept(noexcept(--
std::declval<underlying_iterator_type &>()))
399 requires
std::bidirectional_iterator<underlying_iterator_type>
402 if (--second_it == first_it)
412 constexpr basic_iterator operator--(
int )
413 noexcept(noexcept(std::declval<underlying_iterator_type &>()--))
415 requires
std::bidirectional_iterator<underlying_iterator_type>
418 basic_iterator tmp{*
this};
425 constexpr basic_iterator & operator+=(difference_type
const offset)
426 noexcept(noexcept(std::declval<basic_iterator &>().from_index(1)))
428 requires
std::random_access_iterator<underlying_iterator_type>
431 from_index(to_index() + offset);
437 constexpr basic_iterator operator+(difference_type
const offset)
const
438 noexcept(noexcept(std::declval<basic_iterator &>() += 1))
440 requires
std::random_access_iterator<underlying_iterator_type>
443 basic_iterator tmp{*
this};
444 return (tmp += offset);
449 constexpr
friend basic_iterator operator+(difference_type
const offset, basic_iterator iter)
450 noexcept(noexcept(
std::declval<basic_iterator<range_type> &>().from_index(1)))
452 requires
std::random_access_iterator<underlying_iterator_type>
455 iter.from_index(iter.to_index() + offset);
461 constexpr basic_iterator & operator-=(difference_type
const offset)
462 noexcept(noexcept(std::declval<basic_iterator &>().from_index(1)))
464 requires
std::random_access_iterator<underlying_iterator_type>
467 from_index(to_index() - offset);
473 constexpr basic_iterator operator-(difference_type
const offset)
const
474 noexcept(noexcept(std::declval<basic_iterator &>() -= 1))
476 requires
std::random_access_iterator<underlying_iterator_type>
479 basic_iterator tmp{*
this};
480 return (tmp -= offset);
485 template <
typename other_range_type>
487 requires std::random_access_iterator<underlying_iterator_type> &&
490 constexpr difference_type operator-(basic_iterator<other_range_type>
const & rhs)
const
491 noexcept(noexcept(std::declval<basic_iterator &>().to_index()))
493 return static_cast<difference_type
>(to_index() - rhs.to_index());
507 template <
typename other_range_type>
509 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
512 constexpr
bool operator==(basic_iterator<other_range_type>
const & rhs)
const
513 noexcept(noexcept(std::declval<underlying_iterator_type &>() == std::declval<underlying_iterator_type &>()))
515 return std::tie(first_it, second_it) ==
std::tie(rhs.first_it, rhs.second_it);
519 template <
typename other_range_type>
521 requires std::equality_comparable_with<underlying_iterator_type, std::ranges::iterator_t<other_range_type>> &&
524 constexpr
bool operator!=(basic_iterator<other_range_type>
const & rhs)
const
525 noexcept(noexcept(std::declval<underlying_iterator_type &>() != std::declval<underlying_iterator_type &>()))
527 return !(*
this == rhs);
531 template <
typename other_range_type>
533 requires std::totally_ordered_with<underlying_iterator_type,
534 std::ranges::iterator_t<other_range_type>> &&
537 constexpr
bool operator<(basic_iterator<other_range_type>
const & rhs)
const
538 noexcept(noexcept(std::declval<underlying_iterator_type &>() < std::declval<underlying_iterator_type &>()))
540 return std::tie(first_it, second_it) <
std::tie(rhs.first_it, rhs.second_it);
544 template <
typename other_range_type>
546 requires std::totally_ordered_with<underlying_iterator_type,
547 std::ranges::iterator_t<other_range_type>> &&
550 constexpr
bool operator>(basic_iterator<other_range_type>
const & rhs)
const
551 noexcept(noexcept(std::declval<underlying_iterator_type &>() > std::declval<underlying_iterator_type &>()))
554 return std::tie(first_it, second_it) >
std::tie(rhs.first_it, rhs.second_it);
558 template <
typename other_range_type>
560 requires std::totally_ordered_with<underlying_iterator_type,
561 std::ranges::iterator_t<other_range_type>> &&
564 constexpr
bool operator<=(basic_iterator<other_range_type>
const & rhs)
const
565 noexcept(noexcept(std::declval<underlying_iterator_type &>() <= std::declval<underlying_iterator_type &>()))
567 return std::tie(first_it, second_it) <=
std::tie(rhs.first_it, rhs.second_it);
571 template <
typename other_range_type>
573 requires std::totally_ordered_with<underlying_iterator_type,
574 std::ranges::iterator_t<other_range_type>> &&
577 constexpr
bool operator>=(basic_iterator<other_range_type>
const & rhs)
const
578 noexcept(noexcept(std::declval<underlying_iterator_type &>() >= std::declval<underlying_iterator_type &>()))
580 return std::tie(first_it, second_it) >=
std::tie(rhs.first_it, rhs.second_it);
598 constexpr
size_t to_index() const
599 noexcept(noexcept(
std::declval<underlying_iterator_type &>() -
std::declval<underlying_iterator_type &>()))
601 requires
std::random_access_iterator<underlying_iterator_type>
604 size_t src_size = end_it - begin_it;
605 size_t index_i = first_it - begin_it;
606 size_t index_j = second_it - begin_it;
607 return (src_size * (src_size - 1)/2) - (src_size - index_i) * ((src_size - index_i) - 1)/2 +
608 index_j - index_i - 1;
615 constexpr
void from_index(
size_t const index)
616 noexcept(noexcept(std::declval<underlying_iterator_type &>() - std::declval<underlying_iterator_type &>()) &&
617 noexcept(std::declval<underlying_iterator_type &>() + 1))
619 requires
std::random_access_iterator<underlying_iterator_type>
622 size_t src_size = end_it - begin_it;
623 size_t index_i = src_size - 2 -
625 size_t index_j = index + index_i + 1 - src_size * (src_size - 1)/2 + (src_size - index_i) *
626 ((src_size - index_i) - 1)/2;
627 first_it = begin_it + index_i;
628 second_it = begin_it + index_j;
632 underlying_iterator_type first_it{};
634 underlying_iterator_type second_it{};
636 underlying_iterator_type begin_it{};
638 underlying_iterator_type end_it{};
709 inline constexpr
auto pairwise_combine = detail::adaptor_for_view_without_args<detail::pairwise_combine_view>{};
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:150
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
constexpr auto pairwise_combine
A view adaptor that generates all pairwise combinations of the elements of the underlying range.
Definition: pairwise_combine.hpp:709
Specifies requirements of an input range type for which the const version of that type satisfies the ...
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
Additional non-standard concepts for ranges.
Adaptations of concepts from the Ranges TS.
Provides seqan3::common_tuple and seqan3::common_pair.