Type de modèle à retour automatique et ambiguïté

20

J'ai une fonction de modèle surchargée:

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 je l'appelle comme ça:

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

tout fonctionne parfaitement, mais

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

provoque un appel ambigu.

Pourquoi en est-il ainsi avec int , et OK quels autres types?

amplificateur
la source
4
Je pense que…. La façon dont le compilateur le voit est: avec int, spécifiez-vous le typename RTou le typename T1? Puisque 4c'est aussi un int, ça pourrait être l'un ou l'autre. Avec double, 4ne correspond pas directement au type double, la deuxième surcharge est donc préférable.
ChrisMM
Cela me semble un peu douteux parce que vous êtes en quelque sorte surchargé sur le type de retour, mais avec des modèles qui ont différents paramètres.
Borgleader le

Réponses:

25

RTn'est pas déductible, donc lorsqu'il ne le fournit pas, seul template<typename T1, typename T2> auto overMax(T1 a, T2 b)peut être appelé.

Lorsque vous fournissez (partiellement) un argument de modèle, les deux méthodes sont viables,

mais selon l'argument, on peut être un meilleur candidat:

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

    Les deux overMax<double, int, double>et overMax<double, double>sont viables.
    Mais overMax<double, int, double>est correspondance exacte
    alors que overMax<double, double>nécessite intla doubleconversion.

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

    Les deux overMax<int, int, double>et overMax<int, double>sont viables.
    Mais ni l'un ni l'autre ne correspond mieux ni n'est plus spécialisé, donc l'appel est ambigu.

Jarod42
la source
pourquoi ni l'un ni l'autre ne valent mieux? Ai-je raison de dire que dans le premier cas, overMax <int> (4, 7.2); entraînerait la conversion de 7,2 en int . Et dans le second cas, le résultat retourné, qui est initialement double , serait converti en int en raison de <int> explicite ?
amplificateur
1
@amplifier: overMax<int>(4, 7.2)serait dans le premier cas T1=int(fourni), T2=double(déduit) et dans le second cas RT=int(fourni), T1=int, T2=double(déduit). La définition du contenu des deux méthodes n'est pas utilisée pour sélectionner la surcharge.
Jarod42
quant à moi, le deuxième cas convient, car il y a une conversion de type de retour pour le premier et aucune conversion pour le second, n'est-ce pas?
amplificateur
hmmm ... la conversion du type de retour ne joue pas de rôle ... alors, oui, les deux appels sont équivalents de ce point de vue
amplificateur