I do not think this is a mistake. If you look at the (possible) implementation of std::upper_bound , the comparison is performed as
if (!(value < *it)) { ... }
And since operator< is a member function of MyInt (and not an int , which is not a class type), the code does not compile, since there is no conversion from MyInt to int . On the other hand, in std::lower_bound , *it appears on lhs comparisons, and value (of type int ) can be implicitly converted to MyInt when passed to MyInt::operator< .
if (*it < value) { ... }
It is for this reason that it is better to implement comparison operators as non-members, so you do not have this asymmetry. This is also mentioned in the Scott Meyers C ++ Effect book: Clause 24: Declare non-member functions when type conversions should be applied to all parameters.
Quick and dirty fix: specify MyInt::operator int(){return val;} to implicitly convert MyInt to int . ( EDIT: not working, ambiguity). What works by eliminating the need for implicit conversion
set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), MyInt(2));
instead.
source share