Consider this code:
#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
}
My impression was that the call convention of ranges would be a 1-to-1 mapping of the corresponding original algorithm (i.e., just skip the .begin()
and .end()
, and it should work as before).
Clearly this is not the case here. What am I missing?
A link to the code:
https://godbolt.org/z/3a6z9c5of
0
1 Answer
ranges::find
uses ranges::equal_to
by default to compare the elements of the range with the value, and the call operator of ranges::equal_to
constrains the two types to satisfy equality_comparable_with
, which is S
and int
in your example.
equal_comparable_with
requires S
to be comparable with itself and needs to have a common reference with const int&
, which is not your case.
The simple workaround is to use the projection function to project S
to S::a
if (auto const it{std::ranges::find(iv, 1, &S::a)}; it != iv.end()) {
std::cout << "Found!n" << "n";
}
6
-
1
What is the motivation for
equality_comparable_with
to require the existence of a common reference? What does it have to do with comparison?– Evg11 hours ago
-
1
-
Thanks. Unfortunately, the answer there doesn't really explain the motivation, "the design says", that's all. I guess I need to study the document that answer refers to.
– Evg10 hours ago
-
3
@Evg Well, what does it even mean to say that an
S
(a type with twoint
s in it) is "equal" to anint
? There are certain properties that we think about when we think about equality… soS{1, 2} == 1
andS{1, 3} == 1
, does that imply thatS{1, 2} == S{1, 3}
? ButS
isn't even comparable to itself, so what can we even meaningfully say about this? This example strikes me more like it's using==
for the syntactic convenience offind
more than anything else.– Barry10 hours ago
-
@Evg: motivation of constraints are to have meaningful contraints, i.e just have
operator<
(for ordering) is "strange" (so nooperator >
) (even if it is indeed the "old" C++ way).– Jarod4210 hours ago