Объекты класса, у которого нет оператора == (), преобразуются в другой тип - PullRequest
0 голосов
/ 08 февраля 2019

Почему объекты класса A преобразуются в bool (или в int) в следующем коде:

class A
{
public:

    operator bool() const { return true; }
    operator int() const { return 1; }
};

int main()
{
    return A() == A();
}

и неясно, во что они преобразуются?bool или int?

1 Ответ

0 голосов
/ 09 февраля 2019

Нам нужно найти, что делать с ==.Для этого потребуется поиск участников, не являющихся членами, и встроенных кандидатов на ==.В этом случае у нас нет кандидатов на членство / неучастие, поэтому эта часть проста.

Встроенные кандидаты: [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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...