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.
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.