为什么std::ranges::find无法编译,而std::find却可以正常工作?

15
考虑一下这段代码:
#include <vector>
#include <iostream>
#include <cstdint>
#include <ranges>

int main()
{
    struct S {
        int  a;
        int  b;
        bool operator==(int other) const { return a == other; }
    };
    std::vector<S> iv{
        {1, 2},
        {3, 4}
    };

    // this works
    if (auto const it{std::find(iv.begin(), iv.end(), 1)}; it != iv.end()) {
        std::cout << "Found!\n" << "\n";
    }

    //std::ranges::find(iv, 2); // <-- why does this not compile
    
}

我的印象是,范围的调用约定应该是对应原始算法的一对一映射(即,只需跳过`.begin()`和`.end()`,就可以像以前一样工作)。
显然,在这里并非如此。我错过了什么吗?
代码链接: https://godbolt.org/z/3a6z9c5of

@BЈовић 请参考https://en.cppreference.com/w/cpp/algorithm/ranges/find - undefined
1个回答

18

ranges::find 默认使用 ranges::equal_to 来比较范围中的元素与值,而 ranges::equal_to 的调用运算符要求这两种类型满足 equality_comparable_with,在你的示例中,这两种类型分别是 Sint

equality_comparable_with 要求 S 可与自身进行比较,并且需要与 const int& 具有公共引用,而这并不符合你的情况。

一个简单的解决方法是使用投影函数将 S 投影到 S::a

if (auto const it{std::ranges::find(iv, 1, &S::a)}; it != iv.end()) {
    std::cout << "Found!\n" << "\n";
}

1
equality_comparable_with requires the existence of a common reference in order to ensure that comparison operations can be performed between two objects. This requirement is motivated by the need for equality comparison, which involves comparing the values of two objects to determine if they are equal or not. By having a common reference, the comparison can be carried out effectively and accurately. - undefined
谢谢。不幸的是,那里的回答并没有真正解释动机,“设计所说”的那部分。我猜我需要研究一下那个回答所提到的文件。 - undefined
9
@Evg 嗯,说一个包含两个整数的类型 S 和一个整数 int 是"相等"的,这到底意味着什么呢?当我们思考相等性时,有一些特定的属性我们会考虑... 所以 S{1, 2} == 1S{1, 3} == 1,这是否意味着 S{1, 2} == S{1, 3}?但是 S 甚至不能与自身进行比较,所以我们对此能说什么有意义的呢?这个例子更像是在使用 == 来方便地进行 find 操作,而不是其他什么。 - undefined
@Evg: 约束的动机是为了有有意义的约束,即仅仅有operator<(用于排序)是“奇怪”的(所以没有operator>)(即使它确实是“旧”的C++方式)。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接