¿Cómo se determina la ambigüedad en el algoritmo de resolución de sobrecarga?


Estoy tratando de entender el método de resolución de sobrecarga.

¿Por qué es esto ambiguo:

void func(double, int, int, double) {}
void func(int, double, double, double) {}

void main()
{
    func(1, 2, 3, 4);
}

¿Pero esto no lo es?

void func(int, int, int, double) {}
void func(int, double, double, double) {}

void main()
{
    func(1, 2, 3, 4);
}

En el primer caso hay 2 coincidencias exactas de parámetros y 2 conversiones contra 1 coincidencia exacta y 3 conversiones, y en el segundo caso hay 3 coincidencias exactas y 1 conversión contra 1 coincidencia exacta y 3 conversiones.

Entonces, ¿por qué uno es ambiguo y uno no lo es? ¿Cuál es la lógica aquí?

Author: T. Bergemann, 2015-03-17

3 answers

Las reglas de resolución de sobrecarga solo definen un orden parcial en el conjunto de todas las coincidencias - si una sobrecarga F1 no es una mejor coincidencia que F2, no implica que F2 sea una mejor coincidencia que F1. El orden parcial exacto puede ser considerado como la comparación de dos puntos en k dimensiones, donde el número de argumentos es k. Permite definir este orden parcial en los puntos en k-dim espacio - (x_1, x_2,..., x_k) < (y_1, y_2,..., y_k) if x_i <= y_i for all i and x_j < y_j for at least one j. Este es exactamente el orden parcial en las funciones candidatas no-plantilla definidas por el estándar.

Veamos sus ejemplos :

void func(double, int,    int,    double) {}
                  vvv     vvv       vvv
                 better  better    equal
void func(int,    double, double, double) {}
          vvv                       vvv
         better                    equal

Así que ninguna sobrecarga es estrictamente mejor que la otra.

En tu segundo ejemplo:

void func(int,   int,   int,   double) {}
          vvv    vvv    vvv     vvv
         equal  better better  equal
void func(int, double, double, double) {}
          vvv
         equal

Ahora, la primera sobrecarga es mejor que la segunda en todos menos un argumento Y nunca es peor que la segunda. Por lo tanto, no hay ambigüedad - el orden parcial de hecho declara el primero mejor.

(La descripción anterior no considera plantillas de función. Puede encontrar más detalles en cppreference.)

 54
Author: Pradhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-11 18:42:43

El texto del estándar (§[over.coincidir.mejor]/1) es:

[...] sea ICS i (F) denota 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.
[...] una función viable F1 se define como una función mejor que otra función viable F2 si para todos los argumentos i, ICS i (F1) no es una secuencia de conversión peor que ICS i (F2), y entonces
- para algún argumento j, ICS j (F1) es una mejor secuencia de conversión que ICS j (F2)

En su primer caso, las dos funciones fallan en la primera prueba. Para el primer argumento, la primera función (tomando double) tiene una secuencia de conversión peor que la segunda. Para el segundo argumento, la segunda función tiene una secuencia de conversión peor que la primera (de nuevo, el int tiene que ser promovido a double en un caso, pero no en el otro).

Por lo tanto, ninguna de las funciones pasa la primera regla, y la llamada es ambigua.

Entre el segundo par de funciones, cada argumento para la primera función tiene al menos una conversión tan buena como el argumento coincidente para la segunda función. Luego pasamos a la segunda regla, y encontramos que hay al menos un argumento (dos, de hecho) para el cual la primera función tiene una mejor conversión (identidad en lugar de promoción) que la segunda.

Por lo tanto, la primera función es una mejor partido, y será seleccionado.

 13
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-17 03:38:38

La ambigüedad está determinada por la clasificación:

  1. Coincidencia exacta: no se requiere conversión, conversión lvalue a rvalue, conversión de calificación, conversión definida por el usuario del tipo de clase a la misma clase
  2. Promoción: promoción integral, promoción en coma flotante
  3. Conversión: conversión integral, conversión de punto flotante, conversión de integral flotante, conversión de puntero, conversión de puntero a miembro, conversión booleana, conversión definida por el usuario de una clase derivada a su base

Coincidencia exacta gana vs Promoción que gana vs Conversión.

En el ejemplo:

void func(int, bool, float, int){cout << "int,bool,float,int" << endl;}
void func(int, bool, int, int){cout << "int,int,int,int" << endl;}

int main()
{
    func(1,1,3.4,4);
}

El argumento 1(1) es una coincidencia exacta en ambos
El argumento 2 (1) es una coincidencia exacta en ambos
El argumento 3 (3.4) se puede convertir en float e int - Ambiguity Tampoco es mejor.
Argumento 4(4) es una coincidencia exacta en ambos

Pero si hiciéramos esto: func(1,1,3.4f,4);
(3.4f) ahora es una coincidencia exacta!
void func(int, bool, float, int) entonces gana el batalla.

 0
Author: Andreas DM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-10 04:42:40