Страницы

Поиск по вопросам

понедельник, 8 октября 2018 г.

Неодназначность перегрузки функции разными целыми типами

void f(long long v) { cout << 1; } void f(int v) { cout << 2; } int main() { long l = 2L; f(l); return 0; }
Есть такой код, при этом ошибка компиляции - неоднозначность, а почему?!
Cтандарт C++ гарантирует, что
sizeof(int) <= sizeof(long) <= sizeof(long long)
И по правилам, расширение имеет больше приоритет чем стандартное преобразование.
long в long long - расширение. long в int - стандартное преобразование.
Скорей всего повлияло, в моей модели данных long = int = 4, а long long = 8. Какая тогда должна быть логика? Если long = int, почему бы не выбрать функцию с int аргументом?
Если я попробую заменить long l = 2L на int l = 2, все удачно скомпилируется, из за точного соответствия.
PS: Все попытки на c++14


Ответ

Я не знаю, откуда вы взяли эту информацию о каком-то "расширении", которое якобы "имеет больше приоритет, чем стандартное преобразование".
Язык С++ признает только два типа целочисленных преобразований при выполнении ранжирования неявных преобразований в процессе overload resolution. Это integral promotions и integral conversions (см. Table 12 в 13.3.3.1.2).
Integral promotions - это преобразования, которым подвергаются "малые" целочисленные типы - [signed/unsigned] char и [signed/unsigned] short. Типы int, long и long long не могут подвергаться integral promotions, и к нашему случаю integral promotions никак не относятся.
Все остальные преобразования между целочисленными типами являются integral conversions и имеют один и тот же ранг, независимо от того, являются ли они "расширяющими", "сужающими" или еще какими. В вашем случае преобразования long -> int и long -> long long являются integral conversions.
Фактический размер типов на вашей платформе никакого значения не имеет. Ранжирование неявных преобразований полностью абстрагировано от этих размеров. Тот факт, что на вашей платформе int и long имеют одно и тоже физическое представление ничего не меняет. С точки зрения языка int и long - разные типы и между ними надо выполнять преобразования, пусть даже и чисто концептуальные.
(Да, в С++ есть понятие сужающего (narrowing) преобразования, и преобразование из long в int в общем случае является сужающим, но при выполнении ранжирования неявных целочисленных преобразований этот момент не учитывается вообще.)
В вашем случае обе функции-кандидата требуют integral conversion, т.е. преобразований одного и того же ранга. Значит вызов неоднозначен.

Комментариев нет:

Отправить комментарий