为什么在 std::views::zip 上使用 std::ranges::find 的这段代码不编译?

Why doesn't this code using std::ranges::find on an std::views::zip compile?

提问人:Alberto Santini 提问时间:7/7/2023 更新时间:7/10/2023 访问量:143

问:

以下 C++23 代码不使用 gcc 编译:

#include <ranges>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1{1,2,3,4};
    std::vector<int> v2{2,4,6,8};
    auto z = std::views::zip(v1, v2);

    if(std::ranges::find(z, {2, 4}) != z.end()) {
        std::cout << "(2,4) in zip\n";
    }

    return 0;
}

错误是:

zip.cpp:11:25: error: no match for call to ‘(const std::ranges::__find_fn) (std::ranges::zip_view<std::ranges::ref_view<std::vector<int, std::allocator<int> > >, std::ranges::ref_view<std::vector<int, std::allocator<int> > > >&, <brace-enclosed initializer list>)’

如果我按如下方式更改代码:

#include <ranges>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1{1,2,3,4};
    std::vector<int> v2{2,4,6,8};
    auto z = std::views::zip(v1, v2);

    if(std::ranges::find_if(z, [](auto p){return p == std::make_pair(2, 4);}) != z.end()) {
        std::cout << "(2,4) in zip\n";
    }

    return 0;
}

错误更容易理解:

zip.cpp:10:52: error: no match for ‘operator==’ (operand types are ‘std::pair<int&, int&>’ and ‘std::pair<int, int>’)

有没有办法使类似的代码编译? 需要明确的是,我想要实现的是验证一对元素是否在 zip 视图中。即,如果第一个元素在第一个向量中,则第二个元素在第二个向量中,并且它们的索引相等。

C++ 标准 范围 C++23

评论

3赞 康桓瑋 7/7/2023
P2165 使值类型始终为 ,并为 添加了带有类似对象的比较函数,因此在 C++23 中格式正确(因为可以与 或 进行比较)。你的代码之所以会失败,是因为各种编译器还没有完全实现该提案。zip_viewtupletupletupleranges::find(z, pair-or-tuple-or-array{2, 4})tuplepairtuple

答:

4赞 n. m. could be an AI 7/7/2023 #1

您的代码尝试将 a 与 .这应该没问题,但是似乎没有一个主流编译器有符合 for 对的实现。pair<int,int>pair<int&,int&>operator==

用于指定

template<class T1, class T2>
constexpr bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);

这是当前所有实现所做的。但是,一个相对较新的缺陷报告将其更改为

template<class T1, class T2, class U1, class U2>
constexpr bool operator==(const pair<T1,T2>&, const pair<U1,U2>&);

这解决了问题。它还没有进入编译器。

您必须提供自己的自定义比较器,直到实现赶上 DR。

评论

0赞 康桓瑋 7/7/2023
"然而,似乎没有一个主流编译器有符合 operator== for Pairs 的实现。查看 stackoverflow.com/questions/75268007/...
0赞 n. m. could be an AI 7/7/2023
@康桓瑋啊,所以cpreference是错误的,它说异质比较从一开始就存在。
1赞 n. m. could be an AI 7/8/2023
@AlbertoSantini 我认为除了提供论据之外,您不能在那里做任何事情。std::pair<int&, int&>
1赞 Weijun Zhou 7/10/2023
@n.m.willseey'allonReddit 这并不是真的错,只是 cppreference 处理 DR 的方式令人困惑。如果 DR 已追溯应用于以前的标准,它将在 cppreference 中显示为适用于以前的标准,然后将原始 DR 报告添加到页面的“缺陷报告”部分。
1赞 n. m. could be an AI 7/10/2023
@WeijunZhou 谢谢,我没有意识到它是追溯应用的。