Нам нужно найти, что делать с ==
.Для этого потребуется поиск участников, не являющихся членами, и встроенных кандидатов на ==
.В этом случае у нас нет кандидатов на членство / неучастие, поэтому эта часть проста.
Встроенные кандидаты: [over.built] / 13 (выделено и сокращено):
Для каждой пары повышенных арифметических типов L и R существует оператор-кандидатфункции вида
bool operator==(L, R);
повышенные арифметические типы *1023* являются целочисленными типами после продвижения и типами с плавающей запятой.Любой целочисленный тип меньше int
(включая bool
) повышает до int
.(float
повышает до double
, но float
по-прежнему является "повышенным арифметическим типом").Важной частью этого для нас действительно является то, что «повышенные арифметические типы» включают int
, но не bool
.Таким образом, у нас есть встроенные кандидаты, такие как:
bool operator==(int, int);
bool operator==(int, long);
bool operator==(long, int);
bool operator==(long, long);
bool operator==(int, float);
// etc.
В этом наборе есть лот кандидатов.Но мы можем в основном разделить их на две группы.
Первая группа целиком состоит из:
bool operator==(int, int);
Этот кандидат является жизнеспособным, у нас есть четкая наилучшая последовательность конверсии, поскольку прохождение operator int() const
лучше, чем прохождение operator bool() const
, а затемпродвижение.
Вторая группа состоит из каждого другого кандидата.Для каждого повышенного арифметического типа, который не является int
, у нас есть две эквивалентные последовательности преобразования: одна с помощью преобразования bool
и одна с помощью преобразования int
.Ни один не лучше, чем другой.Когда я впервые написал этот ответ, я подумал, что это означало, что эти кандидаты будут отклонены - но это, на удивление, не так, как указывает TC: неоднозначная последовательность преобразования обрабатывается эквивалентно любому другому определенному пользователемпоследовательность преобразования.
Итак, из первой группы у нас есть один жизнеспособный кандидат, который включает определенную пользователем последовательность преобразования.А из второй группы у нас есть много кандидатов с неоднозначными последовательностями преобразования - что важно считать эквивалентным хорошим operator==(int, int)
кандидату из первой группы.
В результате, A() == A()
плохо сформирован.Нет лучшего жизнеспособного кандидата.GCC не может принять это.
Обратите внимание, что gcc отклоняет очень похожие другие презентации этой же идеи:
void check(int, int);
void check(float, float);
check(A(), A()); // gcc and clang reject, msvc accepts