Tipo de retorno automático de modelo e ambiguidade

20

Eu tenho uma função de modelo sobrecarregada:

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;
}

Se eu chamar assim:

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

tudo funciona perfeito, mas

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

causa chamada ambígua.

Por que é assim com int e OK que outros tipos?

amplificador
fonte
4
Eu acho que .... A maneira como o compilador vê é: com int, você está especificando o typename RTou o typename T1? Como 4também é um int, também pode ser. Com double, 4não corresponde diretamente ao tipo double, portanto, a segunda sobrecarga é preferida.
ChrisMM 15/01
Isso me parece um pouco desonesto, porque você está sobrecarregando o tipo de retorno, mas com modelos com diferentes parâmetros.
Borgleader 15/01

Respostas:

25

RTnão é dedutível, portanto, quando não o fornece, apenas template<typename T1, typename T2> auto overMax(T1 a, T2 b)pode ser chamado.

Quando você (parcialmente) fornece um argumento de modelo, ambos os métodos são viáveis,

mas, dependendo do argumento, pode-se ser um candidato melhor:

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

    Ambos overMax<double, int, double>e overMax<double, double>são viáveis.
    Mas overMax<double, int, double>é correspondência exata
    enquanto que overMax<double, double>exige inta doubleconversão.

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

    Ambos overMax<int, int, double>e overMax<int, double>são viáveis.
    Mas nem uma correspondência melhor ou mais especializada, portanto, a chamada é ambígua.

Jarod42
fonte
por que nenhum deles é muito melhor? Estou certo de que, no primeiro caso, sobre Max <int> (4, 7.2); causaria a conversão de 7,2 para int . E no segundo caso, o resultado retornado, que inicialmente é o dobro , seria convertido em int devido a <int> explícito ?
amplificador
11
@ amplificador: overMax<int>(4, 7.2)seria no primeiro caso T1=int(fornecido), T2=double(deduzido) e no segundo caso RT=int(fornecido), T1=int, T2=double(deduzido). A definição de conteúdo de ambos os métodos não é usada para selecionar sobrecarga.
Jarod42 15/01
quanto a mim, o segundo caso é adequado, já que há conversão de tipo de retorno para o primeiro e nenhuma conversão para o segundo, não é?
amplificador
hmmm ... a conversão de tipo de retorno não desempenha um papel ... então, sim, ambas as chamadas são equivalentes a partir deste ponto de vista
amplificador