Различные операторы приведения, используемые разными компиляторами

Следующая программа на С ++ компилируется без предупреждений во всех пробных компиляторах (gcc 4.6.3, llvm 3.0, icc 13.1.1, SolarisStudio 12.1 / 12.3):

struct CClass
{
template<class T>
operator T() const { return 1; }

operator int() const { return 2; }
};

int main(void)
{
CClass x;
return static_cast<char>(x);
}

Однако все компиляторы, кроме SolarisStudio, возвращают 2, SolarisStudio (любая версия) возвращает 1, что я считаю наиболее логичным результатом.

С помощью return x.operator char(); результаты во всех возвращаемых компиляторах 1.

Очевидно, что после выяснения этого я использовал последнее обозначение. Тем не менее, я хотел бы знать, какой из компиляторов является правильным и почему. (Можно подумать, что большинство правил, но это по-прежнему не объясняет Зачем.)

Этот вопрос, кажется, связан с вопросами SO Вот, Вот, а также Вот, но они «только» дают решения проблем, не дают никаких объяснений (что я все равно смог применить к своей конкретной проблеме).

Обратите внимание, что добавление дополнительного перегруженного оператора приведения, скажем, operator float() const { return 3; } результаты во всех компиляторах, кроме SolarisStudio, жалуются на неоднозначность.

14

Решение

Первая (шаблонная) перегрузка должна быть выбрана.

Пункт 13.3.3 / 1 стандарта C ++ 11 определяет:

[…] жизнеспособная функция F1 определяется как лучшая функция, чем другая жизнеспособная функция
F2 если для всех аргументов i, ICSi(F1) не хуже последовательности преобразования, чем ICSi(F2), а потом

— для некоторого аргумента j, ICSj(F1) является лучшей последовательностью преобразования, чем ICSj(F2)или, если не так,

контекст является инициализацией пользовательским преобразованием (см. 8.5, 13.3.1.5 и 13.3.1.6) и
стандартная последовательность преобразования из возвращаемого типа F1 к типу назначения
(т.е. тип
объект инициализируется) является лучшей последовательностью преобразования, чем стандартная последовательность преобразования из
тип возврата F2 к типу назначения
. [ пример:

struct A {
A();
operator int();
operator double();
} a;
int i = a; // a.operator int() followed by no conversion
// is better than a.operator double() followed by
// a conversion to int
float x = a; // ambiguous: both possibilities require conversions,
// and neither is better than the other

конец примера ] или же, если не то,

F1 это не шаблонная функция и F2 это специализация шаблона функции, или, если не так,

[…]

Как вы можете видеть, тот факт, что первый оператор преобразования является шаблоном, становится релевантным только тогда, когда стандартная последовательность преобразования из его возвращаемого типа (charв данном случае) к типу назначения (charв данном случае) не лучше, чем стандартная последовательность преобразования из типа возврата не шаблонной перегрузки (intв данном случае) к типу назначения (char, в этом случае).

Тем не менее, стандартное преобразование из char в char является Полное совпадение, в то время как стандартное преобразование из int в char не является. Таким образом, третий пункт в п. 13.3.3 / 1 не применяется, а второй пункт применяется.

Это означает, что первая (шаблонная) перегрузка должна быть выбрана.

9

Другие решения

Первое точное совпадение, второе требует преобразования. Точные совпадения имеют приоритет перед конверсией.

Те другие вопросы, которые вы связали, в основном не связаны с вашими.

Несколько советов: не используйте операторы преобразования шаблонов. Назови это convert_to вместо.

5

По вопросам рекламы [email protected]