Home:ALL Converter>Does ranges::lower_bound have different requirements for the comparison than std::lower_bound?

Does ranges::lower_bound have different requirements for the comparison than std::lower_bound?

Ask Time:2021-06-29T16:30:00         Author:Peter H

Json Formatter

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

Author:Peter H,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/68175176/does-rangeslower-bound-have-different-requirements-for-the-comparison-than-std
Caleth :

Yes, it is.\nstd::ranges::lower_bound's Comp must be\nstd::indirect_strict_weak_order<const double*, std::vector<A>::iterator>\n\nwhich expands to lots of variations of\nstd::strict_weak_order<Comp&, const double&, A&>\n\nwhich expand to\nstd::predicate<Comp&, const double&, const double&> &&\nstd::predicate<Comp&, const double&, A&> &&\nstd::predicate<Comp&, A&, const double&> &&\nstd::predicate<Comp&, A&, A&>\n\nSo you need to be able to handle every permutation of parameter types.\nstd::lower_bound's Comp only needs to be Compare, which is fine with just the (A&, const double&) form.",
2021-06-29T08:47:52
yy