Ответ 1
Вы передаете int
этой перегруженной функции.
Хотя человеческая интуиция говорит, что ambig(signed long)
должен быть предпочтительнее, потому что ваш ввод является отрицательным целым числом (которое не может быть представлено как таковое unsigned long
), эти два преобразования фактически эквивалентны в "приоритете" в С++.
То есть, преобразование int
→ unsigned long
считается справедливым как int
→ signed long
, и ни один из них не является предпочтительным для другого.
С другой стороны, если ваш параметр уже был long
, а не int
, то есть точное соответствие signed long
, без необходимости преобразования. Это позволяет избежать двусмысленности.
void ambig( signed long) { }
void ambig(unsigned long) { }
int main(void) { ambig(static_cast<long>(-1)); return 0; }
"Только одна из этих вещей".
[C++11: 4.13/1]:
( "Integer ранг преобразования" )Каждый целочисленный тип имеет целочисленный ранг преобразования, определяемый следующим образом:
- [..]
- Ранг целочисленного типа со знаком должен быть больше ранга любого целочисленного типа со знаком с меньшим размером.
- Ранг
long long int
должен быть больше рангаlong int
, который должен быть больше рангаint
, который должен быть больше чем рангshort int
, который должен быть больше ранга подписанного char.- Ранг любого беззнакового целочисленного типа должен равняться ранга соответствующего знакового целочисленного типа.
- [..]
[Примечание. Integer ранг преобразования используется в определении интегральных повышений (4.5) и обычных арифметических преобразований (п. 5). -end note]
Разрешение перегрузки является сложным и определяется в [C++11: 13.3]
; Я не буду вас утомлять, цитируя здесь большинство.
Здесь выделяется:
[C++11: 13.3.3.1/8]:
Если для сопоставления аргумента с типом параметра не требуется преобразований, неявная последовательность преобразования является стандартной последовательностью преобразования, состоящей из преобразования идентичности (13.3.3.1.1).
[C++11: 13.3.3.1/9]:
Если последовательность преобразований не может быть найдена для преобразования аргумента в тип параметра или преобразование иначе плохо сформировано, неявная последовательность преобразования не может быть сформирована.
[C++11: 13.3.3.1/10]:
Если существует несколько различных последовательностей преобразований, каждая из которых преобразует аргумент в тип параметра, неявная последовательность преобразования, связанная с параметром, определяется как уникальная последовательность преобразования, обозначающая неоднозначную последовательность преобразования. С целью ранжирования неявных последовательностей преобразования, как описано в 13.3.3.2, неоднозначная последовательность преобразования рассматривается как определяемая пользователем последовательность, которая неотличима от любой другой пользовательской последовательности преобразования134. Если функция, использующая неоднозначную последовательность преобразований, выбрана в качестве лучшей жизнеспособной функции, вызов будет плохо сформирован, потому что преобразование одного из аргументов в вызове неоднозначно.
-
/10
- это тот случай, который вы испытываете;/8
- это случай, когда вы используете аргументlong
.