Besoin de comprendre les règles de résolution des modèles de fonctions

Certains détails concernant les règles de résolution de surcharge et de spécialisation des modèles me déroutent vraiment. J’ai essayé de comprendre un peu le sujet en lisant cet article de Herb Sutter sur la surcharge / spécialisation de modèles . Je suis coincé sur le point spécifique suivant dans l’article.

C’est ici

Consider the following code: // Example 2: Explicit specialization // template // (a) a base template void f( T ); template // (b) a second base template, overloads (a) void f( T* ); // (function templates can't be partially // specialized; they overload instead) template // (c) explicit specialization of (b) void f(int*); // ... int *p; f( p ); // calls (c) The result for the last line in Example 2 is just what you'd expect. The question of the day, however, is why you expected it. If you expected it for the wrong reason, you will be very surprised by what comes next. After all, "So what," someone might say, "I wrote a specialization for a pointer to int, so obviously that's what should be called" - and that's exactly the wrong reason. Consider now the following code, put in this form by Peter Dimov and Dave Abrahams: // Example 3: The Dimov/Abrahams Example // template // (a) same old base template as before void f( T ); template // (c) explicit specialization, this time of (a) void f(int*); template // (b) a second base template, overloads (a) void f( T* ); // ... int *p; f( p ); // calls (b)! overload resolution ignores // specializations and operates on the base // function templates only 

La seule différence que je vois entre les exemples 2 et 3 est l’ordre dans lequel les modèles b et c sont déclarés. Je ne comprends pas pourquoi cela fait toute la différence. Quel est l’ordre de déclaration à faire avec quoi que ce soit? Je dois avoir manqué un concept de base de c ++, et je ne vois pas d’explication à cela dans l’article.

J’apprécierais vraiment que quelqu’un clarifie cela pour moi.

Merci.

Quel est l’ordre de déclaration à faire avec quoi que ce soit?

La déclaration d’une spécialisation doit toujours suivre la déclaration du modèle en cours de spécialisation (14.7.3 / 3). Dans l’exemple 2, (c) est une spécialisation explicite de (a) et de (b). Dans l’exemple 3, (c) n’est qu’une spécialisation explicite de (a), puisque (b) la suit.

Lorsque la résolution de surcharge est en cours d’exécution, peu importe si un modèle comporte des spécialisations explicites ou non. Dans les deux exemples, la résolution de surcharge sélectionne le modèle (b) au lieu de (a) car il est plus spécialisé (14.5.6.2). Dans l’exemple 2, le choix est sans importance, car (c) est une spécialisation des deux modèles et est donc appelé à tout moment. Dans l’exemple 3, c’est important. Parce que (b) gagne la résolution de surcharge et que (c) n’est pas une spécialisation de (b), il s’ensuit que (c) n’est pas appelé.

Dans le deuxième exemple, la spécialisation se produit pour le modèle de class T , car le modèle de class T* n’a même pas encore été déclaré au moment où la spécialisation est déclarée.

Ainsi, lorsque le compilateur cherche le modèle qui correspond le mieux, il choisit correctement le modèle de class T* , qui n’a aucune spécialisation.