С++ 20 явно использует оператор равенства по умолчанию

Я пытаюсь понять новые операторы сравнения по умолчанию, представленные в С++ 20. Моя проблема связана с тем, что оператор сравнения с явным значением по умолчанию определяется неявно. Следующий пример кода иллюстрирует вопрос:

#include <iostream>

struct B
{
  operator bool() const { return true; }
};

struct D : B
{
  bool operator==(const D&) const = default;
};

bool operator==(B, B) { return false; }

int main ()
{ D d;
  std::cout << (d == d);
}

/* Outputs:
0   in gcc 10.1
1   in msvc 19.26
*/

Вывод этой программы зависит от компилятора. Кажется, что MSVC определяет оператор == для класса D, когда он сталкивается с объявлением по умолчанию, поэтому он не использует оператор ==, который определен позже для класса B. Напротив, gcc ожидает с неявным определением D. operator== до тех пор, пока он действительно не понадобится, и к этому времени оператор ==, определенный для B, находится в области видимости и используется. Какое поведение является правильным?

Связанный с этим вопрос: почему оператор == по умолчанию не может быть объявлен для класса со ссылочными членами? Я мог видеть, что ссылочные члены могут создавать проблемы с подходом MSVC, потому что ссылочные члены могут ссылаться на неполный тип, когда встречается объявление по умолчанию для operator==. При подходе gcc тип ссылки всегда будет полным до того, как gcc попытается определить оператор по умолчанию.


person user1958486    schedule 17.07.2020    source источник
comment
Связанный с этим вопрос: почему оператор == по умолчанию не может быть объявлен для класса со ссылочными элементами? Это вообще не связанный с этим вопрос.   -  person Nicol Bolas    schedule 17.07.2020


Ответы (1)


GCC ошибается здесь (что неудивительно, учитывая его результаты). При создании определения оператора сравнения по умолчанию стандарт говорит:

Поиск имени в заданном по умолчанию определении функции оператора сравнения выполняется из контекста, эквивалентного телу функции.

А тело функции по умолчанию находится там, где = default это. Поэтому функция bool operator==(B, B) не должна быть видна телу функции оператора сравнения по умолчанию.

person Nicol Bolas    schedule 17.07.2020
comment
Спасибо за быстрый ответ. Я отмечаю, что предложение, непосредственно предшествующее тому, которое вы цитируете, гласит: функция оператора сравнения для класса C, которая по умолчанию используется при первом объявлении и не определяется как удаленная, определяется неявно, когда она используется odr или требуется для постоянной оценки. Я думаю, было бы яснее, если бы когда было изменено на если. - person user1958486; 17.07.2020