S'il vous plaît, expliquez-moi pourquoi le code suivant est conforme et fonctionne parfaitement ... Je suis très confus.
#include<iostream>
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <int, B>
{
public:
Base()
{
std::cout<<"it works!!!!!\n";
}
};
int main()
{
Base<> base; // it prints "it works!!!!!"
return 0;
}
Ne devrait-il pas tomber sous la forme généralisée de la classe de modèle Base?
L'argument par défaut s'applique à la spécialisation - et, en fait, une spécialisation doit accepter (pour ainsi dire) le ou les arguments par défaut du modèle de base. Tentative de spécifier une valeur par défaut dans la spécialisation:
template<class A = int, class B=double>
class Base
{};
template<class B=char>
// ...
... est une erreur.
De même, si nous modifions la spécialisation de sorte que sa spécialisation concerne un type autre que celui par défaut fourni par le modèle de base:
template<class A = int, class B=double>
class Base
{};
template<class B>
class Base <char, B>
... alors le modèle de base sera choisi.
Donc, voici ce qui se passe: d’abord, les types des arguments de modèle sont choisis. Dans ce cas (aucun type spécifié à l'instanciation), les deux types sont basés sur les arguments de modèle par défaut spécifiés dans le modèle de base.
Ensuite (en tant qu'étape fondamentalement séparée), il effectue une résolution analogique de la résolution de surcharge sur tous les modèles qui correspondent à ces types d'argument. Comme d'habitude pour la résolution de surcharge, un type spécifié explicitement est préféré à un type spécifié implicitement. Votre spécialisation (qui a explicitement spécifié int
) est préférée au modèle de base (qui a implicitement défini int
).
template<class A = int, class B=double>
class Base
{};
Ici, les valeurs par défaut/initialisation pour A et B ont été déclarées respectivement int et double.
template<class B>
class Base <int, B>
Ici, dans les définitions de classe, le premier argument est quelque chose qui ressemble à une valeur constante (ici, pourquoi déclarez-vous simplement de manière à complexifier les choses? Supprimez le premier argument du modèle) et le deuxième argument est B, dont la valeur par défaut est 'double'.
Base<> base;
Lorsque vous créez l'objet de la classe. Bien que vous ne spécifiez pas les arguments du modèle, le compilateur prend les valeurs par défaut des arguments (A et B), qui sont 'int' et 'double', et le code s'exécute sans erreur ni avertissement .
Voyez ce qui se passe lorsque vous créez l'objet en tant que:Base<float,char> b;
ou Base<char,char> b;
Lorsque vous écrivez Base<> base;
, le compilateur essaiera de déterminer si l’instanciation de la classe Base<>
est possible ou non, mais si cela est possible, le code fonctionnerait correctement . sait que si vous écrivez Base<>
, vous devez créer un objet de Base<int,double>
. c'est-à-dire à cause de:
template<class A = int, class B=double>
class Base
{};
Donc, le code fonctionne bien.