Estás pasando de int
a esta función sobrecargada.
Aunque la intuición humana dice que ambig(signed long)
debe ser preferida debido a que su entrada es un entero negativo (que no puede ser representado como tal por un unsigned long
), los dos conversiones son, de hecho, equivalente en "precedencia" en C++.
Es decir, la conversión int
→ unsigned long
se considera que es tan válida como int
→ signed long
, y tampoco se prefiere a la otra.
Por otro lado, si su parámetro eran ya un long
en lugar de un int
, entonces no es una coincidencia exacta -signed long
, sin necesidad de conversión. This avoids the ambiguity.
void ambig( signed long) { }
void ambig(unsigned long) { }
int main(void) { ambig(static_cast<long>(-1)); return 0; }
"Sólo una de esas cosas".
[C++11: 4.13/1]:
("rango conversión entera")
Cada tipo entero tiene un rango de conversión de número entero define como sigue:
- [..]
- El rango de un tipo entero con signo debe ser mayor que el rango de cualquier tipo entero con signo con un tamaño más pequeño.
- El rango de
long long int
será mayor que el rango de long int
, que deberá ser mayor que el rango de int
, que deberá ser mayor que el rango de short int
, que deberá ser mayor que el rango de firmado carbonizarse.
- El rango de cualquier tipo de entero sin signo será igual al rango del tipo de entero con signo correspondiente.
- [..]
[Nota: El rango de conversión de número entero se utiliza en la definición de las promociones integrales (4.5) y las conversiones aritméticas usuales (Cláusula 5). -end nota]
resolución de sobrecarga es complejo, y se define en [C++11: 13.3]
; No te aburriré citando la mayoría aquí.
Aquí es un punto culminante, sin embargo:
[C++11: 13.3.3.1/8]:
Si no se requieren conversiones para que coincida con un argumento para un tipo de parámetro, la secuencia de conversión implícita es la secuencia de conversión estándar que consiste en la conversión de identidad (13.3.3.1. 1).
[C++11: 13.3.3.1/9]:
Si no se puede encontrar una secuencia de conversiones para convertir un argumento a un tipo de parámetro o si la conversión no está bien formada, no se puede formar una secuencia de conversión implícita.
[C++11: 13.3.3.1/10]:
Si existen varias secuencias de conversiones diferentes que convierten cada argumento al tipo de parámetro, la secuencia de conversión implícita asociada con el parámetro se define como la secuencia de conversión única designada como la secuencia de conversión ambigua. Con el fin de clasificar las secuencias de conversión implícitas como se describe en 13.3.3.2, la secuencia de conversión ambigua se trata como una secuencia definida por el usuario que no se distingue de cualquier otra secuencia de conversión definida por el usuario134. Si se selecciona una función que utiliza la secuencia de conversión ambigua como la mejor función viable, la llamada estará mal formada porque la conversión de uno de los argumentos en la llamada es ambigua.
/10
es el caso que está experimentando; /8
es el caso que usa con un argumento long
.
Espera, pero 'int' →' long' es siempre una conversión sin pérdida. 'int' →' unsigned long' pierde la mitad de las veces. ¿Cómo/por qué son del mismo rango? – Mehrdad
Simplemente curioso: ¿hay alguna razón para no usar solo '-1L' en lugar de ese molde? – Mat
@Mat: No, ninguno. –