С++ неоднозначный вызов перегруженной функции с целым числом без знака

Это кажется непоследовательным. У меня есть 3 функции f, перегруженные для подписанных типов short, int и long long. Если вы передадите unsigned short, то он будет повышен до следующего крупнейшего подписанного типа int. Однако, если вы передадите unsigned int, то он не будет повышен до подписанного long long, чего я и ожидал, скорее компилятор жалуется на неоднозначный вызов перегруженной функции.

void f(short x) { std::printf("f(short)\n"); }
void f(int x) { std::printf("f(int)\n"); }
void f(long long x) { std::printf("f(long long)\n"); }

int main()
{
    f((unsigned short)0); // Fine: calls f(int)
    // f((unsigned int)0); // Ambiguous: could be f(short), f(int) or f(long long) 
}

person George Skelton    schedule 26.10.2016    source источник
comment
Почему вы ожидаете этого и каков ваш вопрос? Почему это так? или как сделать его менее двусмысленным?   -  person 463035818_is_not_a_number    schedule 26.10.2016
comment
Да какое обоснование?   -  person George Skelton    schedule 26.10.2016


Ответы (2)


Да, это непоследовательно, но это Путь Языка, и вам приходится с этим справляться, например. если вы хотите, чтобы f((unsigned int)0) вызывал перегрузку long long, предоставьте оболочку,

inline void f(unsigned int x) { f((long long)x); }

Разработчики C++ в идеале хотели бы сделать оба ваших случая fail разрешением перегрузки. Но была эта устаревшая вещь (начиная с «K&R» C), называемая «продвижение аргумента по умолчанию», которая, по сути, говорит, что компилятор будет неявно преобразовывать все целочисленные типы, более узкие, чем int, в int, если это необходимо для соответствия функции. подпись, и все типы с плавающей запятой уже, чем double до double то же самое.

Так что случай f((unsigned short)0) действительно лишний.

person zwol    schedule 26.10.2016

http://en.cppreference.com/w/cpp/language/implicit_conversion

Интегральное продвижение не увеличивает ваш рейтинг с unsigned int до long long.

Интегральное продвижение действительно повышает ваш рейтинг с unsigned short до int.

Интегральное преобразование из unsigned int считается одинаково хорошим для ваших перегрузок.

Повышение заканчивается на int и/или unsigned int, если только ваш исходный тип не является enum, для которого требуется более крупный целочисленный тип.

Продвижение предпочтительнее конверсии, поэтому ваш первый случай однозначен. Во втором случае пути продвижения нет, поэтому ваш код неоднозначен.

person Yakk - Adam Nevraumont    schedule 26.10.2016