This code works and returns an iterator to foo{5}
from the vector:
struct foo {
int value;
};
auto main() -> int {
auto ints = std::vector<foo>{{3}, {2}, {5}, {6}, {7}, {0}, {4}, {6}};
std::ranges::sort(ints, {}, &foo::value);
auto it = std::upper_bound(
ints.begin(), ints.end(),
4,
[](const int v, const foo f) {
return v < f.value;
}
);
}
This, however, doesn't compile:
struct foo {
int value;
};
auto main() -> int {
auto ints = std::vector<foo>{{3}, {2}, {5}, {6}, {7}, {0}, {4}, {6}};
std::ranges::sort(ints, {}, &foo::value);
auto it = std::ranges::upper_bound( // the only change - added ::ranges
ints,
4,
[](const int v, const foo f) {
return v < f.value;
}
);
std::cout << it->value;
}
Is the alteration of the behavior intentional or accidental?
The error message boils down to not satisfying the following constraint:
note: the expression 'is_invocable_v<_Fn, _Args ...> [with _Fn = main::._anon_76&; _Args = {int&, int&}]' evaluated to 'false'
Well, yeah, you can't call that with two int&
s. I suspect it may be intentional since the "standard" way would be to use the projection like so:
struct foo {
int value;
};
auto main() -> int {
auto ints = std::vector<foo>{{3}, {2}, {5}, {6}, {7}, {0}, {4}, {6}};
std::ranges::sort(ints, {}, &foo::value);
auto it = std::ranges::upper_bound(ints, 4, {}, &foo::value); // using projection
std::cout << it->value;
}
Is this the rationale? Looking at the fairly complilated signature of template parameters of std::ranges::upper_bound
didn't really shine any light on it for me.