c++ - polarité - tableau priorité fonctions chimie organique




Priorité des fonctions du modèle C++ (2)

#include <iostream>

template <class U, class T>
void foo(U&, T&)
{
    std::cout << "first";
}

template <class T>
void foo(int&, const T&)
{
    std::cout << "second";
}

int main()
{
    int a;
    double g = 2.;
    foo(a, g); // prints "first"

    return 0;
}

Pour appeler la deuxième surcharge foo , le compilateur doit effectuer une seule déduction de type de modèle, mais pour la première surcharge, il doit effectuer deux. Pouvez-vous s'il vous plaît expliquer pourquoi la première surcharge est appelée?


La résolution de surcharge est effectuée en plusieurs étapes.

Tout d'abord, grâce à la recherche de noms, nous sélectionnons la liste des candidats viables. Dans ce cas, c'est:

template <class U, class T>
void foo(U&, T&);            // with U = int, T = double

template <class T>
void foo(int&, const T&)     // with T = double

Ensuite, nous déterminons la séquence de conversion nécessaire pour chaque argument pour chaque candidat viable. C'est [over.ics.rank]:

La séquence de conversion standard S1 est une meilleure séquence de conversion que la séquence de conversion standard S2 si [...]

  • S1 est une sous-séquence propre de S2 (comparant les séquences de conversion sous la forme canonique définie au 13.3.3.1.1, excluant toute transformation Lvalue, la séquence de conversion d'identité est considérée comme une sous-séquence de toute séquence de conversion sans identité) ou pas ça,
  • le rang de S1 est meilleur que le rang de S2, ou S1 et S2 ont le même rang et peuvent être distingués par les règles du paragraphe ci-dessous ou, si ce n'est pas le cas,

Pour le premier appel, la séquence de conversion est (Identité, Identité). Pour le second appel, la séquence de conversion est (Identité, Identité). Donc nous sommes égaux là-bas. Aucun de ces points de balle ne distingue les deux appels. Alors nous passons à autre chose.

  • S1 et S2 sont des liaisons de référence (8.5.3) et aucune ne fait référence à un paramètre d'objet implicite d'une fonction membre non statique déclarée sans qualificatif ref, et S1 lie une référence rvalue à une valeur rvalue et S2 lie une référence lvalue.

Sans importance.

  • S1 et S2 sont des liaisons de référence (8.5.3) et S1 lie une référence lvalue à une fonction lvalue et S2 lie une référence rvalue à une fonction lvalue.

Nan.

  • S1 et S2 ne diffèrent que par leur conversion de qualification et produisent des types similaires T1 et T2 (4.4), respectivement, et la signature de qualification cv de type T1 est un sous-ensemble propre de la signature de qualification cv de type T2.

La conversion de qualification est une chose de pointeur, non.

  • S1 et S2 sont des liaisons de référence (8.5.3), et les types auxquels se réfèrent les références sont du même type sauf pour les qualificatifs cv de niveau supérieur, et le type auquel se réfère la référence initialisée par S2 est plus qualifié cv que le type auquel se réfère la référence initialisée par S1.

Dans ce cas, la première surcharge prend son deuxième argument comme double& tandis que la deuxième surcharge prend un const double& . Le premier étant moins qualifié que le second, nous nous arrêtons ici - préférant foo(U&,T&) .

Ce n'est qu'après les étapes pour déterminer quelle séquence de conversion est la meilleure que nous arrivons à l'étape où le modèle plus spécialisé est préféré. L'ordre complet des règles dans [over.match.best] est:

Compte tenu de ces définitions, une fonction viable F1 est définie comme étant une meilleure fonction qu'une autre fonction viable F2 si pour tous les arguments i, ICSi (F1) n'est pas une séquence de conversion pire que ICSi (F2), puis

  • pour certains arguments j, ICSj (F1) est une meilleure séquence de conversion que ICSj (F2), ou, sinon,

C'est ce que nous venons de traverser.

  • le contexte est une initialisation par conversion définie par l'utilisateur [...]
  • le contexte est une initialisation par la fonction de conversion pour la liaison de référence directe [...]
  • F1 n'est pas une spécialisation de modèle de fonction et F2 est une spécialisation de modèle de fonction, ou sinon,
  • F1 et F2 sont des spécialisations de modèle de fonction, et le modèle de fonction pour F1 est plus spécialisé que le modèle pour F2 selon les règles d'ordre partiel décrites au § 14.5.6.2.

C'est pourquoi nous choisissons foo(U&, T&) . Cependant, si vous supprimez le const , les deux séquences de conversion sont identiques dans toutes les étapes. Ainsi, le modèle le plus spécialisé ( foo(int&, T&) ) gagnera.

Notez que plus spécialisé est le dernier mécanisme pour déterminer le meilleur candidat. C'est le plus définitif des bris d'égalité.

Notez également que le nombre de déductions de modèle est non pertinent. Il peut être important de choisir entre une surcharge qui est un modèle et une surcharge qui n'est pas un modèle - mais cela n'a pas d'importance de choisir entre une surcharge qui a des paramètres de modèle x et une surcharge qui a des paramètres de modèle y> x .


Observer:

  • La première surcharge prend un lvalue non-const comme deuxième argument
  • La deuxième surcharge prend une valeur constante comme deuxième argument

Comme vous passez g tant que valeur non-const, le compilateur choisit la première surcharge.





overload-resolution