Source: https://ffff65535.com/es/q/88082a
Timestamp: 2019-12-14 17:06:22+00:00

Document:
c++ - funciones - ¿Debería esto compilar? Resolución de sobrecarga y conversiones implícitas. : Dev
c++ - funciones - ¿Debería esto compilar? Resolución de sobrecarga y conversiones implícitas.
ejemplos datos (2)
Este ejemplo parece compilar con VC10 y gcc (aunque mi versión de gcc es muy antigua).
EDIT: R. Martinho Fernández probó esto en gcc 4.7 y el comportamiento sigue siendo el mismo.
Pero clang se queja:
La resolución de sobrecarga está considerando dos funciones posibles al mirar esta expresión:
llamando a Something :: operator [] (después de una conversión definida por el usuario)
llamando al operador incorporado para const char * (piense "32" [d]) (después de que una conversión definida por el usuario y una conversión estándar doble a larga).
Si hubiera escrito d["32"] como d.operator[]("32") , entonces la resolución de sobrecarga ni siquiera se verá en la opción 2, y el clang también se compilará bien.
EDITAR: (aclaración de preguntas)
Esto parece ser un área complicada en la resolución de sobrecargas, y por eso apreciaría muchas respuestas que expliquen en detalle la resolución de sobrecargas en este caso, y cite el estándar (si hay alguna regla desconocida / avanzada que probablemente sea desconocida) .
Si el clang es correcto, también me interesa saber por qué los dos son ambiguos / uno no es preferido sobre otro. La respuesta probablemente tendría que explicar cómo la resolución de sobrecarga considera las conversiones implícitas (tanto las conversiones estándar como las definidas por el usuario) involucradas en los dos candidatos y por qué uno no es mejor que el otro.
Nota: si el operador double () se cambia a operador bool (), los tres (clang, vc, gcc) se negarán a compilar con un error ambiguo similar.
Debería ser más fácil imaginar por qué la resolución de la sobrecarga es ambigua si se realiza paso a paso.
Por lo tanto, una expresión de subíndice x[y] se interpreta como x.operator[](y) para un objeto de clase x de tipo T si T::operator[](T1) existe y si el operador se selecciona como la función de mejor coincidencia Por el mecanismo de resolución de sobrecarga (13.3.3) .
Ahora, primero necesitamos un conjunto de sobrecarga. Se construye de acuerdo con §13.3.1 y contiene miembros y funciones no miembros. Vea esta respuesta mía para una explicación más detallada.
p2 El conjunto de funciones candidatas puede contener funciones miembro y no miembro que se deben resolver en la misma lista de argumentos. De modo que las listas de parámetros y argumentos son comparables dentro de este conjunto heterogéneo, se considera que una función miembro tiene un parámetro adicional, denominado parámetro objeto implícito, que representa el objeto para el cual se ha llamado la función miembro . [...]
p3 De manera similar, cuando sea apropiado, el contexto puede construir una lista de argumentos que contenga un argumento de objeto implícito para denotar el objeto a operar.
Entonces, se construye una lista de argumentos:
Y luego la lista de argumentos se prueba contra todos los miembros del conjunto de sobrecarga:
Luego, como descubrimos que hay conversiones implícitas requeridas, echamos un vistazo a §13.3.3 [over.match.best] p1 :
Defina ICSi(F) como sigue:
si F es una función miembro estática, [...]; de otra manera,
deje que ICSi(F) denote la secuencia de conversión implícita que convierte el i -ésimo argumento en la lista al tipo del i -ésimo parámetro de la función viable F 13.3.3.1 define las secuencias de conversión implícitas y 13.3.3.2 define lo que significa que una secuencia de conversión implícita sea una mejor secuencia de conversión o una secuencia de conversión peor que otra.
Ahora construyamos esas secuencias de conversión implícitas para f1 y f2 en el conjunto de sobrecarga ( §13.3.3.1 ):
una secuencia de conversión estándar (13.3.3.1.1) es una mejor secuencia de conversión que una secuencia de conversión definida por el usuario o una secuencia de conversión de puntos suspensivos.
Entonces, ICS1(f1) es mejor que ICS1(f2) e ICS2(f1) ICS1(f1) es mejor que ICS1(f2) ICS2(f2) .
Por el contrario, ICS1(f2) es peor que ICS1(f1) e ICS2(f2) es mejor que ICS2(f1) .
p1 (cont.) Dadas estas definiciones, una función viable F1 se define como una mejor función que otra función viable F2 si, para todos los argumentos i , ICSi(F1) no es una secuencia de conversión peor que ICSi(F2) , y luego [ ...]
p2 Si hay exactamente una función viable que es una función mejor que todas las demás funciones viables, entonces es la seleccionada por resolución de sobrecarga; De lo contrario la llamada está mal formada.
Bueno, f * ck. :) Como tal, Clang tiene razón al rechazar ese código.
Parece que no hay duda de que tanto Something::operator[](const foo& f) como el operator[](long, const char *) integrado operator[](long, const char *) son funciones candidatas viables (13.3.2) para la resolución de sobrecargas. Los tipos de argumentos reales son Something y const char* , y las secuencias de conversión implícitas (ICF) creo que son:
for Something::operator[](const foo& f) : (1-1) conversión de identidad, y (1-2) foo("32") través de foo::foo(const char*) ;
para el operator[](long, const char *) : (2-1) long(double(d)) través de Something::operator double() const (heredado de Base), y (2-2) conversión de identidad.
Ahora, si clasificamos estos ICF de acuerdo con (13.3.3.2), podemos ver que (1-1) es una conversión mejor que (2-1), y (1-2) es una conversión peor que (2-2) . Según la definición en (13.3.3),
una función viable F1 se define como una función mejor que otra función viable F2 si, para todos los argumentos i, ICSi (F1) no es una secuencia de conversión peor que ICSi (F2), ...
Por lo tanto, ninguna de las dos funciones candidatas consideradas es mejor que la otra, y por lo tanto la llamada está mal formada. Es decir, Clang parece ser correcto, y el código no debe compilarse.
type tipos sobrecarga hacer funciones ejemplos datos conversion como c++ visual-c++ clang implicit-conversion overload-resolution
¿Por qué este programa es rechazado erróneamente por tres compiladores de C++?
Resolución de sobrecarga con ref-calificadores.
En la resolución de sobrecarga, ¿la selección de una función que usa la secuencia de conversión ambigua necesariamente hace que la llamada no esté bien formada?
¿Este cambio en la resolución de sobrecarga entre Clang 3.5 y 3.6 es correcto o es un error?
Resolución de sobrecarga para el operador heredado múltiple()

References: Resolución 
 Resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución 

Resolución 
 resolución 
 resolución 

Resolución