Вы передаете int
этой перегруженной функции.
Хотя человеческая интуиция говорит, что ambig(signed long)
должно быть предпочтительным, потому что ваш ввод - отрицательное целое число (которое не может быть представлено как таковоеunsigned long
), эти два преобразования на самом деле эквивалентны в «приоритете» в C ++.
То есть преобразование 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]:
("Целочисленный рейтинг конверсии")
Каждый целочисленный тип имеет ранг целочисленного преобразования, определенный следующим образом:
- [..]
- Ранг целочисленного типа со знаком должен быть большечем ранг любого целочисленного типа со знаком меньшего размера.
- ранг
long long int
должен быть больше ранг long int
, который долженбыть больше, чем ранг int
, который должен быть больше, чем ранг short int
, который должен быть больше, чем ранг подписанного символа. - ранг любого неподписанногоЦелочисленный тип должен равняться рангу соответствующего целочисленного типа со знаком.
- [..]
[ Примечание: Используется целочисленный ранг преобразованияв определении интегральных продвижений (4.5) и обычных арифметических преобразований (п. 5). - конец примечания ]
Разрешение перегрузки является сложным и определяется в [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
.