Приоритет перегруженных операторов
В приведенном ниже коде я ожидал бы получить ошибку компилятора, если из-за неоднозначности определено несколько операторов-операторов.
#include <iostream>
#include <sstream>
struct A
{
operator const char*() { return "hello world\n"; }
operator float() { return 123.0F; }
//operator int() { return 49; }
};
int main()
{
A a;
std::stringstream ss;
ss << a;
std::cout << ss.str();
return 0;
}
Вместо этого, если определен только один оператор с числовым литьем, он компилируется без ошибок, без предупреждений, а числовое преобразование используется в предпочтении operator const char *()
. Порядок заявленных операторов не имеет значения.
Однако, если operator int()
и operator float()
оба определены, я получаю то, что я ожидал с самого начала:
'< < неоднозначно
Существуют ли правила приоритета для кастомий или почему компилятор выбирает числовое значение по умолчанию? Я понимаю, что я должен явно указать, какое действие я имею в виду, но мой вопрос касается выбора по умолчанию, который делает компилятор.
Изменить: использование компилятора MSVC 2010
Ответы
Ответ 1
Конверсии ранжируются в соответствии с § 13.3.3.1 Стандарта С++. В частности, пользовательские последовательности преобразований, относящиеся к вашему примеру, регулируются § 13.3.3.1.2/1:
"Пользовательская последовательность преобразований состоит из начальной стандартной последовательности преобразования, за которой следует пользовательское преобразование (12.3), за которым следует вторая стандартная последовательность преобразования. [...] Если пользовательское преобразование задается (12.3.2), начальная стандартная последовательность преобразования преобразует тип источника в неявный параметр объекта функции преобразования."
Все последовательности преобразований включают в себя:
- фиктивное преобразование в тип источника неявного параметра объекта функции преобразования;
- пользовательское преобразование;
- преобразование идентичности в тип ввода
operator <<
.
Эти последовательности преобразования имеют одинаковый ранг. Таким образом, вызов должен быть неоднозначным. Если это не так, для меня это ошибка компилятора.