верхние и нижние границы несовместимые требования к значениям

Я видел, что выглядит как несоответствие в синтаксисах std :: lower_bound () и std :: upper_bound () (ну, на самом деле, преобразование типов), и мне было интересно, если кто-нибудь может объяснить, пожалуйста? Согласно комментариям, строка 2 не будет компилироваться, несмотря на ее очевидное сходство со строкой 1; вам нужно использовать форму, показанную в строке 3 (по крайней мере, на gcc 4.7.3 / ubuntu 64-bit — это все, с чем я должен играть)

#include <set>
#include <algorithm>

using namespace std;

class MyInt {
private:
int val;
public:
MyInt(int _val): val(_val) {}
bool operator<(const MyInt& other) const {return val < other.val;}
};

int main() {
set<MyInt> s;
s.insert(1);  // demonstrate implicit conversion works
s.insert(MyInt(2));
s.insert(3); // one last one for the road
set<MyInt>::iterator itL = lower_bound(s.begin(), s.end(), 2); //LINE 1
// the line below will NOT compile
set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), 2); //LINE 2
// the line below WILL compile
set<MyInt>::iterator itU2 = upper_bound(s.begin(), s.end(), MyInt(2)); // LINE 3
return 0;
}

5

Решение

Я не думаю, что это ошибка. Если вы посмотрите на (возможная) реализация std::upper_bound, сравнение сделано как

if (!(value < *it)) { ... } // upper_bound, implicit conversion `MyInt`->`int` doesn't work

И потому что operator< является функцией-членом MyInt (а не из int, который не является типом класса), код не компилируется, так как нет преобразования из MyInt в int, С другой стороны, в std::lower_bound, *it появляется на левой части сравнения, и value (типа int) может быть неявно преобразовано в MyInt когда перешел к MyInt::operator<,

if (*it < value) { ... } // lower_bound, implicit conversion `int`->`MyInt` works

По этой причине лучше реализовывать операторы сравнения, не являющиеся членами, поэтому у вас нет этой асимметрии. Это также упоминается в Скотт Мейерс Эффективный C ++ книга: Правило 24. Объявление функций, не являющихся членами, когда преобразования типов должны применяться ко всем параметрам.

Быстрое и грязное исправление: определите MyInt::operator int(){return val;} для неявного преобразования MyInt в int. (РЕДАКТИРОВАТЬ: на самом деле не работает, двусмысленность). Что работает, так это устраняет необходимость неявного преобразования

set<MyInt>::iterator itU = upper_bound(s.begin(), s.end(), MyInt(2));

вместо.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]