/ / (No) Tipo de conversión al llamar a operadores sobrecargados - c ++ 11, conversión, sobrecarga del operador, cadenas en C

(No) Tipo de conversión al llamar a operadores sobrecargados: c ++ 11, conversión, sobrecarga del operador, cadenas de caracteres

Me pregunto si hay una opción para deshabilitar (?) El tipo de conversión al inicializar / comparar objetos con variables de tipo específico:

class X {
//...
const bool operator<=(const long long val) const;
const bool operator<=(const char* val) const;
const X& operator=(const long long val);
const X& operator=(const char* val);
}

int main() {
X x1 = 10;                //thats ok
X x2 = "123";             //ok again
X x3 = 0;                 //error, 0 is "valid" char*
x1 <= 0 ? true : false;   //error, same reason
}

Aquí está el error: more than one operator "<=" matches these operands

¿Hay alguna manera de deshacerse de estos errores? Sé que puedo echar en main pero desafortunadamente eso no es lo que quiero, o de hecho incluso se me permite hacer:

X x3 = (long long)0; //no no no...

También no std::string.


Respuesta (parcial) Por lo tanto, la parte de la asignación se puede resolver cambiando la declaración de clase, eliminando long long Asignar y hacer constructores propios explícitos / implícitos.

// allow implicit conversion from long long, ex. X x = 13;
X(long long val)

// disable implicit conversion from const char*, now X x = 0 is ok - calls the above
explicit X(const char* val);

// allow assignment from const char as well, no confusion with 0 now
const X& operator=(const char*);

Respuestas

1 para la respuesta № 1

La razón por la que la llamada es ambigua es que ambas sobrecargas tienen el mismo rango de conversión estándar, según la tabla 12 en 13.3.3.1.1 [over.ics.scs] en el estándar 14882: 2011 ISO C ++. UNA 0 literal es de tipo int. Una conversión a long long es una conversión integral (ver 4.7), y una conversión a const char* es una conversión de puntero (ver 4.10).

La solución más fácil es simplemente agregar sobrecargas para int. Usted podría simplemente llamar al long long versión del constructor / operador apropiado al enviar el argumento a long long, al igual que:

class X
{
public:
// ...

X(int i) : X((long long)i) { }
const X& operator=(int i) { return operator=((long long)i); }
// etc
};

Su solución parcial "funciona", aunque la segunda línea en main() en tu ejemplo ya no se compilará. Porque una conversión de const char* se hace explícito, ya no se le permite hacer esto:

X x = "Hi there!"; // error: no implicit conversion from const char[10] to X
X x("Hi there!");  // ok

Otra advertencia es que las operaciones con un long long podría ser potencialmente costoso, dependiendo de su implementación de X, porque primero se debe construir una X temporal antes de realizar la asignación / comparación / etc.