Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Если первый операнд аддитивного выражения может быть преобразован как в указатель, так и в целое число, какое преобразование выбрано?

Автор вопроса: willjОтветов: 1

Какую функцию преобразования следует вызвать в следующем примере? Почему следует предпочесть одно другому?

struct A
{
  operator int();
  operator int*();
};

A x;
int i = x + 1;

Компилятор выбирает operator int() .. но почему?

Вот некоторые актуальные цитаты из C ++ 03:

От [expr.add]

В качестве дополнения, оба операнда должны иметь арифметический или перечислительный тип, или один операнд должен быть указателем на полностью определенный тип объекта, а другой должен иметь целочисленный или перечисляемый тип.

От [конв.]

выражения с заданным типом будут неявно преобразованы в другие типы в нескольких контекстах:

  • При использовании в качестве операндов операторов. Требования оператора к его операндам диктуют тип назначения.
  • Я бы сказал, что это должно быть двусмысленно. Я не думаю, что указатели более особенные. chris 16.07.2013
  • Он вызывает другой, если вы говорите int *i = x + 1;? John 16.07.2013
  • @John, нет, он просто жалуется на int -> int *. chris 16.07.2013
  • Что ж, я быстро просмотрел § 13.3.3.2 (Ранжирование последовательностей неявных преобразований) и не нашел ничего особенного, относящегося к этому. chris 16.07.2013

c++type-conversionoverloadinglanguage-lawyerimplicit-conversion

Ответы

Ответ 1 · рейтинг 9 · Andy Prowl

Причина такого поведения в том, что встроенный оператор, который принимает указатель в качестве своего левого операнда, принимает объект типа std::ptrdiff_t в качестве своего правого операнда. Это указано в § 13.6 стандарта C ++ 11:

Для каждого cv-квалифицированного или cv-неквалифицированного типа объекта T существуют кандидатные операторные функции вида

T * operator+(T *, std::ptrdiff_t);

[...]

Поскольку 1 имеет тип int, компилятор рассматривает встроенный operator +, который принимает два int, как лучший выбор, потому что для него требуется только (определяемое пользователем) преобразование для первого аргумента.

Если вы предоставили аргумент типа std::ptrdiff_t как правый операнд operator +, вы увидите ожидаемую двусмысленность:

int i = x + static_cast<std::ptrdiff_t>(1); // AMBIGUOUS!

Вот живой пример.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы