Tipo de devolución automática de plantilla y ambigüedad


20

Tengo una función de plantilla sobrecargada:

template<typename T1, typename T2>
auto overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

template<typename RT, typename T1, typename T2>
RT overMax(T1 a, T2 b)
{
    std::cout << __FUNCSIG__ << std::endl;

    return b < a ? a : b;
}

Si lo llamo así:

auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template

todo funciona perfecto, pero

auto c = overMax<int>(4, 7.2); // error

provoca llamadas ambiguas.

¿Por qué es así con int y OK qué otros tipos?


44
Creo que ... La forma en que el compilador lo ve es: con int, ¿está especificando el typename RTo el typename T1? Como 4también es un int, podría ser cualquiera. Con double, 4no coincide directamente con el tipo double, por lo que se prefiere la segunda sobrecarga.
ChrisMM

Esto me parece un poco dudoso porque estás sobrecargando el tipo de retorno pero con plantillas que tienen una cantidad diferente de parámetros.
Borgleader

Respuestas:


25

RTno es deducible, por lo que cuando no se proporciona, solo template<typename T1, typename T2> auto overMax(T1 a, T2 b)se puede llamar.

Cuando proporciona (parcialmente) un argumento de plantilla, ambos métodos son viables,

pero dependiendo del argumento, uno puede ser un mejor candidato:

  • por auto b = overMax<double>(4, 7.2); // uses second template

    Ambos overMax<double, int, double>y overMax<double, double>son viables.
    Pero overMax<double, int, double>es coincidencia exacta
    mientras que overMax<double, double>se requiere intpara doublela conversión.

  • por auto c = overMax<int>(4, 7.2); // Ambiguous call

    Ambos overMax<int, int, double>y overMax<int, double>son viables.
    Pero ninguno de los dos es mejor o más especializado, por lo que la llamada es ambigua.


¿Por qué ninguno de ellos es mucho mejor? ¿Tengo razón en que en el primer caso overMax <int> (4, 7.2); causaría la conversión de 7.2 a int . Y en el segundo caso, el resultado devuelto, que inicialmente es doble , se convertiría a int debido a <int> explícito ?
amplificador

1
@amplificador: overMax<int>(4, 7.2)sería en el primer caso T1=int(proporcionado), T2=double(deducido) y en el segundo caso RT=int(proporcionado), T1=int, T2=double(deducido). La definición de contenido de ambos métodos no se utiliza para seleccionar la sobrecarga.
Jarod42

En cuanto a mí, el segundo caso es adecuado, ya que hay conversión de tipo de retorno para el primero y ninguna conversión para el segundo, ¿no?
amplificador

hmmm ... la conversión de tipo de retorno no juega un papel ... entonces, sí, ambas llamadas son equivalentes desde este punto de vista
amplificador
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.