ошибка: нет совпадения для 'operator ==', но действительно определено в базовом классе - PullRequest
1 голос
/ 05 мая 2020
struct BaseA {
    auto operator==(const BaseA& other) const {return other.a == a;}
    int a;
};

struct B {
    int b;
};

struct A: public BaseA {
    auto operator==(const B& other) const {return other.b == a;}
};

int main() {
    A a{10};
    a == a;

    return 0;
}

Он не компилируется:

error: no match for ‘operator==’ (operand types are ‘A’ and ‘A’)
note: candidate: ‘auto A::operator==(const B&) const’
note: no known conversion for argument 1 from ‘A’ to ‘const B&’

Не перечисляет BaseA::operator== в качестве кандидата.

Однако, если я закомментирую метод A::operator==, он компилируется.

Из-за этого я подумал, что операторы сравнения получают некоторую особую обработку (иногда генерируются для дочернего класса, иногда нет, как те, что из правила пяти), но после быстрого поиска оказывается, что нет случай.

Некоторые правила перегрузки оператора, то?

Ответы [ 3 ]

4 голосов
/ 05 мая 2020

auto operator==(const B& other) const скрывает базовый, используйте using

struct A: public BaseA {
    using BaseA::operator==;
    auto operator==(const B& other) const {return other.b == a;}
};

Demo

1 голос
/ 05 мая 2020

Здесь нет ничего особенного в операторах, вы получите аналогичную ошибку с:

struct BaseA {
    auto foo(const BaseA& other) const {return other.a == a;}
    int a;
};

struct B {
    int b;
};

struct A: public BaseA {
    auto foo(const B& other) const {return other.b == a;}
};

int main() {
    A a{10};
    a.foo(a);
}

Компилятор находит foo в A и останавливается на этом. Если вы хотите иметь и то, и другое, вам нужно явно вывести его в область действия:

struct A: public BaseA {
    auto foo(const B& other) const {return other.b == a;}
    using BaseA::foo; 
};
0 голосов
/ 06 мая 2020

Я нашел исправление, без записи using для каждого оператора сравнения, который я добавляю в дочерний класс:

Сделайте оператор нечленом и вытащите его в охватывающую область A (в этом примере глобальная область):

auto operator==(const A&, const B&)

Если вы хотите получить доступ к закрытым членам A или защищенным из его базовый класс, вы можете сделать оператора другом A. (То же самое для B.)

Почему это работает

скрытие (это означает, что если имя найдено в области видимости, оно не будет искать в следующем (те, которые алгоритм поиска рассмотрит на следующем шаге), это не остановит работу, потому что для операторов выполняются два отдельных поиска, последовательно объединяемых:

Для оператора, используемого в выражении (например, operator +, используемого в a + b), выполняются два отдельных поиска: для перегрузок операторов, не являющихся членами, и для перегрузок операторов-членов (для операторов, для которых разрешены обе формы). Эти наборы затем объединяются со встроенными перегрузками операторов на равных основаниях.

- cppreference

Таким образом, не член operator== пространство имен не помешает поиску BaseA::operator==, который ищется при поиске оператора-члена, начиная с A (но сейчас нет operator==), поэтому переход к следующей области, базовому классу BaseA .


Этот способ исправления важен для меня, потому что я использую библиотеку строгих типов и просто хотел добавить только один оператор для строгого типа, оборачивая целое число. Я использую библиотеку, чтобы не писать шаблон сам, и все же каждый раз, когда я добавляю оператор, мне приходилось бы use тот, который есть в библиотеке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...