Estoy aprendiendo sobre la sobrecarga de funciones en C ++ y encontré esto:
void display(int a)
{
cout << "int" << endl;
}
void display(unsigned a)
{
cout << "unsigned" << endl;
}
int main()
{
int i = -2147483648;
cout << i << endl; //will display -2147483648
display(-2147483648);
}
Por lo que entendí, cualquier valor dado en el intrango (en mi caso intes de 4 bytes) llamará display(int)y cualquier valor fuera de este rango será ambiguo (ya que el compilador no puede decidir qué función llamar). Es válido para el rango completo de intvalores excepto su valor mínimo, es decir, -2147483648cuando la compilación falla con el error
la llamada de sobrecargado
display(long int)es ambigua
Pero tomar el mismo valor en an inte imprimir el valor da 2147483648. Estoy literalmente confundido con este comportamiento.
¿Por qué se observa este comportamiento solo cuando se pasa el número más negativo? (El comportamiento es el mismo si shortse usa a con -32768- de hecho, en cualquier caso donde el número negativo y el número positivo tengan la misma representación binaria)
Compilador utilizado: g ++ (GCC) 4.8.5
fuente

call of overloaded ‘display(long int)’ is ambiguous.typeof(-2147483648) != int. El literal es2147483648, que es demasiado grande para unint, por lo que es unlong, y está siendo negadoint j{-2147483648};es una conversión estrecha. Casi vale la pena una pregunta en sí misma, eso. Probablemente esté relacionado con permitir (p. Ej.)long longValores constexpr, por ejemplo, que se reduzcan2147483647LLen la inicialización.Respuestas:
Este es un error muy sutil. Lo que está viendo es una consecuencia de que no hay literales enteros negativos en C ++. Si miramos [lex.icon] obtenemos que un entero-literal ,
puede ser un decimal-literal ,
donde dígitos es
[0-9]y distinto de cero dígitos es[1-9]y el sufijo par puede ser uno deu,U,l,L,ll, oLL. En ninguna parte aquí se incluye-como parte del literal decimal.En §2.13.2, también tenemos:
(énfasis mío)
Lo que significa que el
-in-2147483648es el unariooperator -. Eso significa-2147483648que en realidad se trata como-1 * (2147483648). Como2147483648es demasiado para tiint, se promueve along inty la ambigüedad proviene de que no coincide.Si desea obtener el valor mínimo o máximo para un tipo de manera portátil, puede usar:
fuente
-2147483647 - 1también funcionaría sin previo aviso como una expresión literal negativaINT_MINpara la opción menos detallada. Aunque menos genérico.display(2147483649);? ¿Por qué no puede llamar a la función int sin firmar en este caso? y ¿por qué trata el argumento2147483649como int largo en lugar de int sin firmar?intalong intalong long int. Nunca obtendrá un tipo sin signo para un literal decimal a menos que use el sufijou/U.display(unsigned a)necesitadisplay(1234u);odisplay(static_cast<unsigned>(1234));ounsigned foo = 1234; display(foo);La expresión en
-2147483648realidad aplica el-operador a la constante2147483648. En su plataforma,intno se puede almacenar2147483648, debe estar representado por un tipo más grande. Por lo tanto,-2147483648no se deduce que la expresión seasigned intun tipo con signo más grande,signed long int.Dado que no proporciona una sobrecarga,
longel compilador se ve obligado a elegir entre dos sobrecargas que son igualmente válidas. Su compilador debería emitir un error de compilador sobre sobrecargas ambiguas.fuente
Ampliando las respuestas de los demás
Para aclarar por qué se confunde el OP, primero : considere la
signed intrepresentación binaria de2147483647, a continuación.A continuación, agregue uno a este número : dando otro
signed intde-2147483648(que el OP desea usar)Finalmente: podemos ver por qué el OP se confunde cuando se
-2147483648compila en a enlong intlugar de asigned int, ya que claramente cabe en 32 bits.Pero, como mencionan las respuestas actuales, el operador unario (
-) se aplica después de resolver2147483648cuál es along inty NO cabe en 32 bits.fuente