Посмотрите на типы:
auto zip = ranges::views::zip(v1, v2);
// ranges::zip_view<
// ranges::ref_view<std::vector<int>>
// ranges::ref_view<std::vector<char>>
// >
auto begin = std::begin(zip);
// ranges::basic_iterator<
// ranges::iter_zip_with_view<
// ranges::detail::indirect_zip_fn_,
// ranges::ref_view<std::vector<int>>,
// ranges::ref_view<std::vector<char>>
// >::cursor<false>
// >
using traits = std::iterator_traits<decltype(begin)>;
static_assert(std::is_same_v<traits::value_type, std::pair<int, char>>);
static_assert(std::is_same_v<traits::reference, ranges::common_pair<int&, char&>>);
Тип value_type
представляет собой std::pair
значений. Тип reference
представляет собой ranges::common_pair
ссылок.
std::sort
использует std::iter_swap
, который указан в терминах разыменования итераторов и вызова std::swap
. Так что std::sort
попытается поменять местами две ranges::common_pair
ссылки. С другой стороны, ranges::actions::sort
использует ranges::iter_swap
, который настроен для обработки пар и кортежей ссылок.
Пары и кортежи ссылок являются / были гражданами второго сорта в стандартной библиотеке.
ranges::actions::unique
требует стираемого диапазона, который, очевидно, не удовлетворяет.
Добавлено
Документация для range-v3 является разреженной. Чтобы найти такую информацию, как приведенная выше, мы, конечно, ищем источник для range-v3, быстрые эксперименты на godbolt.org (range-v3 - доступная библиотека) и «стандартные» трюки C ++ для поиска типа переменной. (например, вызов шаблона функции, который объявлен, но не определен, с типом переменной в качестве аргумента шаблона, и выяснение, какой экземпляр вызывается).
Комментировать больше unique
, ranges::action::unique
не означает вернуть итератор. Он стирает неуникальные элементы и возвращает диапазон (см. источник ). В части ошибки компилятора, которая была пропущена, ошибка ссылается на тот факт, что диапазон не стирается (скрыт в большой ошибке).
ranges::unique
возвращает итератор и может быть вызван без ошибки. Это basic_iterator<...>
. Один из вариантов - использовать ranges::distance
, чтобы найти расстояние от begin
zip-итератора, и использовать его, чтобы получить базовый итератор:
auto zip_uniq_iter = ranges::unique(zip);
auto first_uniq_iter = std::next(v1.begin(), ranges::distance(ranges::begin(zip), zip_uniq_iter));