gpt4 book ai didi

c++ - 了解 range-v3 中的 zip 是如何工作的

转载 作者:行者123 更新时间:2023-12-02 10:17:48 28 4
gpt4 key购买 nike

我试图了解 range::views::zip 在 range-v3 中的工作原理。我知道这是一个范围,它允许通过在不同范围内创建元素的元组来在一个循环中迭代多个范围。

std::vector<int> v1 = {0, 1, 2};
std::vector<char> v2 = {'a', 'b', 'c'};


auto zip = ranges::views::zip(v1,v2);
// zip(v1,v2) = [(0,a), (1,b), (2,c)]

ranges::actions::sort(zip);
std::sort(std::begin(zip), std::end(zip));

使用 ranges::actions 进行排序工作正常,但 std::sort不编译并给出以下错误
/usr/include/c++/9.3.0/bits/stl_algobase.h:151: error: no matching function for call to ‘swap(concepts::return_t<ranges::common_pair<int&, double&>, void>, concepts::return_t<ranges::common_pair<int&, double&>, void>)’
151 | swap(*__a, *__b);
| ~~~~^~~~~~~~~~~~

为什么会这样?

我还尝试同时删除两个容器中的元素。 ranges::actions::unique编译时出现以下错误:
/home/jjcasmar/projects/cpfsofaplugin/src/CPFSofaPlugin/minimalExample.cpp:27: error: no match for call to ‘(const ranges::actions::action_closure<ranges::actions::unique_fn>) (ranges::zip_view<ranges::ref_view<std::vector<int, std::allocator<int> > >, ranges::ref_view<std::vector<double, std::allocator<double> > > >&)’
27 | ranges::actions::unique(v1Andv2);
| ^

但是 auto lastIt = std::unique(std::begin(v1Andv2), std::end(v1Andv2))编译找到,虽然我不知道如何让 zip 的内部迭代器能够删除结束元素。

我真的不明白这是如何在幕后工作的,以及为什么在某些情况下 std 算法可以正常工作,但在某些情况下却不行。有人可以对此给出一些解释吗?

最佳答案

查看类型:

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的值(value)观。 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不返回迭代器。它删除非唯一元素并返回一个范围(参见 the source )。在省略的编译器错误的一部分中,该错误引用了该范围不可删除的事实(隐藏在一个巨大的错误中)。
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));

关于c++ - 了解 range-v3 中的 zip 是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61351815/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com