Почему std::greater() не работает с самонаписанной структрурой?
У меня есть структура triple, для которой определен оператор больше:
struct triple
{
int c, v, u;
triple(int cn, int vn, int un)
{
c = cn, v = vn, u = un;
}
bool operator >(triple n)
{
if (c > n.c)
return true;
return false;
}
};
Если я пытаюсь запустить следующий код, то программа падает с ошибкой C2678 (бинарный ">": не найден оператор, принимающий левый операнд типа "const _Ty" (или приемлемое преобразование отсутствует)):
int main()
{
triple a(10, 1, 2);
triple b(20, 2, 3);
priority_queue<triple, vector<triple>, greater<triple>> q;
q.push(a);
q.push(b);
return 0;
}
Если вне структуры объявить оператор больше с нужной сигнатурой и такой реализацией, то программа падает с ошибкой Stack overflow:
bool operator >(const triple& a, const triple& b)
{
return a > b;
}
А в такой реализации программа отрабатывает правильно и без ошибок, хотя по идее она ничем не отличается от предыдущей:
bool operator >(const triple& a, const triple& b)
{
if (a.c > b.c)
return true;
return false;
}
Сам вопрос: Почему плюсы не могут сравнить константные выражения по ссылке так же, как и обычные? И как можно объявить нужный оператор сравнения внутри самой структуры, чтобы он не путался под ногами вне ее определения?
Ответы (1 шт):
В таком виде как вы написали, оператор может вызываться только для не константных объектов, а operator() объекта greater<triple> принимает ссылки на константные объекты, поэтому нужно переписать оператор:
struct triple
{
//...
bool operator >(const triple& n) const
//добавлен const, чтобы вызвать для константных объектов тоже
{
return c > n.c;
}
};
Тогда не будет никакой ошибки. Теперь рассмотрим другой вариант.
Когда вы определяете оператор вне структуры(как свободный оператор), то так:
bool operator >(const triple& a, const triple& b)
{
return a > b;
}
Вы практически в операторе рекурсивно вызываете этот же оператор, поэтому кроме как переполнения стека, ничего не случается. То, что у вас работает многим отличается от этого оператора. Он уже сравнивает члены, для которых определен оператор сравнения.
Если убрать лишнюю писанину, то рабочий оператор то же самое, что и:
bool operator >(const triple& a, const triple& b)
{
return a.c > b.c;
}
Заметили различие с предыдущим оператором?...