C'est en fait assez simple. Pour t[1]
la résolution des surcharges a ces candidats :
Candidat 1 (intégré : 13.6/13) (T étant un type d'objet arbitraire) :
- Liste des paramètres :
(T*, ptrdiff_t)
Candidat 2 (votre opérateur)
- Liste des paramètres :
(TData<float[100][100]>&, something unsigned)
La liste des arguments est donnée par 13.3.1.2/6
:
L'ensemble des fonctions candidates pour la résolution des surcharges est l'union des candidats membres, des candidats non membres et des candidats intégrés. La liste des arguments contient tous les opérandes de l'opérateur.
- Liste d'arguments :
(TData<float[100][100]>, int)
Vous voyez que le premier argument correspond exactement au premier paramètre du candidat 2. Mais il faut une conversion définie par l'utilisateur pour le premier paramètre du candidat 1. Donc, pour le premier paramètre, le second candidat l'emporte.
Vous voyez également que le résultat de la deuxième position dépend. Faisons quelques hypothèses et voyons ce que nous obtenons :
-
ptrdiff_t
es int
: Le premier candidat l'emporte, car il a une correspondance exacte, tandis que le second candidat nécessite une conversion intégrale.
-
ptrdiff_t
es long
: Aucun des deux candidats ne gagne, car les deux requièrent une conversion intégrale.
Maintenant, 13.3.3/1
dit
Soit ICSi(F) la séquence de conversion implicite qui convertit le i-ième argument de la liste au type du i-ième paramètre de la fonction viable F.
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 pire séquence de conversion que ICSi(F2), et si ... pour un certain argument j, ICSj(F1) est une meilleure séquence de conversion que ICSj(F2), ou, si ce n'est pas cela ...
Pour notre première hypothèse, nous n'obtenons pas de gagnant global, car le candidat 2 l'emporte pour le premier paramètre, et le candidat 1 pour le second. Je l'appelle le entrecroisé . Pour notre deuxième hypothèse, le candidat 2 l'emporte globalement, car aucun des deux paramètres n'avait une conversion plus mauvaise, mais le premier paramètre avait une conversion plus mauvaise. meilleur conversion.
Pour la première hypothèse, il importe peu que la conversion intégrale (int en unsigned) dans le deuxième paramètre soit un moindre mal que la conversion définie par l'utilisateur de l'autre candidat dans le premier paramètre. Dans le croisement, les règles sont grossières.
Ce dernier point peut encore vous déconcerter, en raison de tout ce qui se passe autour, alors prenons un exemple
void f(int, int) { }
void f(long, char) { }
int main() { f(0, 'a'); }
Cela vous donne le même avertissement GCC déroutant (qui, je m'en souviens, m'a vraiment dérouté lorsque je l'ai reçu pour la première fois il y a quelques années), car 0
se convertit en long
pire que 'a'
a int
- Pourtant, vous obtenez une ambiguïté, car vous êtes dans une situation de croisement.