killogre
killogre

Reputation: 1800

Strict weak ordering of different types in stl algorithms

I have a class that defines a strict weak ordering with other types, and I would like to use comparison-based algorithms on a container of that class (e.g. std::upper_bound).

The standard defines that the container's forward iterator value type should be that of the comparable type, so the following doesn't compile:

template<typename T>
class Foo {
public:
    bool operator<(const T& _val) { return val < _val; }
    //operator T() { return val; } // uncommenting this solves the problem
private:
    T val;
};

void bar() {
    vector<Foo<int>> foos(10);
    auto i_lb = std::lower_bound(foos.begin(), foos.end(), 17); // compiles and works, though I don't know why
    auto i_eq = std::equal_range(foos.begin(), foos.end(), 17); // error! not convertible to int
}

I couldn't find a way of using the algorithm version that accepts the predicate (also requires the types to be the same). Defining a conversion operator makes this example work, but it's not always right to define one. What is the right way of making such a comparison work?

Incidentally, replacing std::equal_range with std::lower_bound works, but I cannot figure out why.

Upvotes: 2

Views: 344

Answers (1)

Bo Persson
Bo Persson

Reputation: 92311

The equal_range will have to compare the values both ways to determine if they are equal

A value, a, is considered equivalent to another, b, when (!(a<b) && !(b<a))

lower_bound just has to find one end of the range.

You comparison just works for Foo < T, and not for T < Foo.

Upvotes: 3

Related Questions