It seems that using the same comparison functor that worked fine with std::lower_bound() does not work with std::ranges::lower_bound() in C++20. The following code does not compile with either Visual Studio 16.10.2 (and /std::c++latest) or gcc 11.1. I can work around the issue by using a projection instead of a comparison functor, but that increases the effort for migration.
Are the requirements for the argument "comp" in std::ranges::lower_bound() different from std::lower_bound(), and if so, how?
#include <algorithm>
#include <vector>
struct A {
double m_value;
};
struct MyComparison {
bool operator()(const A& a, const double& b) {
return a.m_value < b;
}
};
void f() {
std::vector<A> v = {A{1.0}, A{2.0}, A{3.0}};
// comparison functor without ranges compiles as expected:
auto x = std::lower_bound(v.cbegin(), v.cend(), 2.0, MyComparison());
// projection with ranges compiles as expected:
auto y = std::ranges::lower_bound(v, 2.0, {}, &A::m_value);
// comparison functor with ranges fails to compile:
auto z = std::ranges::lower_bound(v, 2.0, MyComparison());
}
Error messages in Visual Studio:
error C2672: 'operator __surrogate_func': no matching overloaded function found
error C7602: 'std::ranges::_Lower_bound_fn::operator ()': the associated constraints are not satisfied
Yes, it is.
std::ranges::lower_bound
's Comp
must be
std::indirect_strict_weak_order<const double*, std::vector<A>::iterator>
which expands to lots of variations of
std::strict_weak_order<Comp&, const double&, A&>
which expand to
std::predicate<Comp&, const double&, const double&> &&
std::predicate<Comp&, const double&, A&> &&
std::predicate<Comp&, A&, const double&> &&
std::predicate<Comp&, A&, A&>
So you need to be able to handle every permutation of parameter types.
std::lower_bound
's Comp
only needs to be Compare, which is fine with just the (A&, const double&)
form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With