c++ - siendo literal `0` un candidato válido para int y const string y sobrecargas causa una llamada ambigua
overloading ambiguous-call (2)
Mi pregunta es por qué el compilador solo se quejó cuando el parámetro era 0.
Porque 0 no es solo un literal entero, sino que también es un literal de puntero nulo. 1 no es un puntero literal nulo, por lo que no hay ambigüedad.
La ambigüedad surge del constructor de conversión implícito de
std::string
que acepta un puntero a un carácter como argumento.
Ahora, la conversión de identidad de int a int sería preferible a la conversión de puntero a cadena, pero hay otro argumento que implica una conversión: el argumento objeto implícito.
En un caso, la conversión es de
CppSyntaxA&
a
CppSyntaxA&
mientras que en otro caso es de
CppSyntaxA&
a
const CppSyntaxA&
.
Por lo tanto, se prefiere una sobrecarga debido a un argumento, y la otra sobrecarga se prefiere debido a otro argumento y, por lo tanto, no existe una sobrecarga inequívocamente preferida.
El problema se solucionará haciendo que ambas funciones consten.
Si ambas sobrecargas están calificadas por
const
, entonces la secuencia de conversión implícita del argumento del objeto es idéntica y, por lo tanto, una de las sobrecargas es inequívocamente preferida.
He arreglado un error recientemente.
En el siguiente código, una de las funciones sobrecargadas era const y la otra no. El problema se solucionará haciendo que ambas funciones consten.
Mi pregunta es por qué el compilador solo se quejó cuando el parámetro era 0.
#include <iostream>
#include <string>
class CppSyntaxA
{
public:
void f(int i = 0) const { i++; }
void f(const std::string&){}
};
int main()
{
CppSyntaxA a;
a.f(1); // OK
//a.f(0); //error C2666: ''CppSyntaxA::f'': 2 overloads have similar conversions
return 0;
}
0
es especial en C ++.
Un puntero nulo tiene el valor de
0
por lo que C ++ permitirá la conversión de
0
a un tipo de puntero.
Eso significa que cuando llamas
a.f(0);
Podría estar llamando a
void f(int i = 0) const
con un
int
con el valor de
0
, o podría llamar a
void f(const std::string&)
con un
char*
inicializado a nulo.
Normalmente, la versión
int
sería mejor ya que es una coincidencia exacta, pero en este caso la versión
int
es
const
, por lo que requiere "convertir"
a
a una
const CppSyntaxA
, donde la versión
std::string
no requiere tal conversión, pero sí requiere una conversión a
char*
y luego a
std::string
.
Esto se considera un cambio suficiente en ambos casos para considerarse una conversión igual y, por lo tanto, ambiguo.
Al hacer ambas funciones
const
o non
const
se solucionará el problema y se elegirá la sobrecarga
int
, ya que es mejor.