Que signifie template ?

En déclarant un modèle, j’ai l’habitude d’avoir ce type de code:

template  

Mais dans cette question , ils ont utilisé:

 template  

J’ai vérifié qu’il comstack. Mais qu’est-ce que ça veut dire? Est-ce un paramètre non typé? Et si oui, comment pouvons-nous avoir un modèle sans paramètre de type?

Il est parfaitement possible de modéliser une classe sur un entier plutôt que sur un type. Nous pouvons assigner la valeur de modèle à une variable ou la manipuler d’une manière qui pourrait être avec tout autre littéral entier:

 unsigned int x = N; 

En fait, nous pouvons créer des algorithmes qui évaluent au moment de la compilation (à partir de Wikipedia ):

 template  struct Factorial { enum { value = N * Factorial::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 } 

Oui, c’est un paramètre non typé. Vous pouvez avoir plusieurs types de parameters de modèle

  • Paramètres de type
    • Les types
    • Modèles (uniquement les modèles de classes et d’alias, aucune fonction ou modèle de variable)
  • Paramètres non typés
    • Pointeurs
    • Les références
    • Expressions constantes intégrales

Ce que vous avez là est du dernier type. C’est une constante de temps de compilation (dite expression constante) et est de type entier ou énumération. Après l’avoir recherché dans la norme, j’ai dû déplacer les modèles de classe dans la section types – même si les modèles ne sont pas des types. Mais ils sont appelés parameters de type dans le but de décrire ces types néanmoins. Vous pouvez avoir des pointeurs (ainsi que des pointeurs de membre) et des références à des objects / fonctions qui ont un lien externe (ceux qui peuvent être liés à d’autres fichiers objects et dont l’adresse est unique dans l’ensemble du programme). Exemples:

Paramètre de type de modèle:

 template struct Container { T t; }; // pass type "long" as argument. Container test; 

Paramètre entier du modèle:

 template struct Vector { unsigned char bytes[S]; }; // pass 3 as argument. Vector<3> test; 

Paramètre du pointeur de modèle (passage d’un pointeur à une fonction)

 template struct FunctionWrapper { static void call_it() { F(); } }; // pass address of function do_it as argument. void do_it() { } FunctionWrapper< &do_it> test; 

Paramètre de référence de modèle (en passant un entier)

 template struct SillyExample { static void do_it() { A = 10; } }; // pass flag as argument int flag; SillyExample test; 

Paramètre de modèle de modèle

 template 

Un modèle sans aucun paramètre n’est pas possible. Mais un modèle sans argument explicite est possible – il a des arguments par défaut:

 template struct Vector { unsigned char buffer[SIZE]; }; Vector<> test; 

De manière syntaxique, le template<> est réservé pour marquer une spécialisation de modèle explicite, au lieu d’un modèle sans parameters:

 template<> struct Vector<3> { // alternative definition for SIZE == 3 }; 

Vous templatize votre classe basée sur un «unsigned int».

Exemple:

 template  class MyArray { public: private: double data[N]; // Use N as the size of the array }; int main() { MyArray<2> a1; MyArray<2> a2; MyArray<4> b1; a1 = a2; // OK The arrays are the same size. a1 = b1; // FAIL because the size of the array is part of the // template and thus the type, a1 and b1 are different types. // Thus this is a COMPILE time failure. } 

Une classe de modèle est comme une macro, mais beaucoup moins mal.

Pensez à un modèle en tant que macro. Les parameters du modèle sont remplacés par une définition de classe (ou de fonction) lorsque vous définissez une classe (ou une fonction) à l’aide d’un modèle.

La différence est que les parameters ont des “types” et que les valeurs transmises sont vérifiées lors de la compilation, comme les parameters des fonctions. Les types valides sont vos types C ++ standard, comme int et char. Lorsque vous instanciez une classe de modèle, vous transmettez une valeur du type que vous avez spécifié et, dans une nouvelle copie de la définition de classe de modèle, cette valeur est remplacée partout où le nom du paramètre était dans la définition d’origine. Tout comme une macro.

Vous pouvez également utiliser les types ” class ” ou ” typename ” pour les parameters (ils sont vraiment identiques). Avec un paramètre de l’un de ces types, vous pouvez transmettre un nom de type au lieu d’une valeur. Tout comme avant, partout où le nom du paramètre était dans la définition de la classe du modèle, dès que vous créez une nouvelle instance, il devient le type que vous transmettez. C’est l’utilisation la plus courante pour une classe de modèle. Tout le monde qui sait quelque chose sur les modèles C ++ sait comment faire cela.

Considérez cet exemple de code de classe de modèle:

 #include  template  class foo { void print() { printf("%i", I); } }; int main() { foo<26> f; f.print(); return 0; } 

C’est fonctionnellement la même chose que ce code utilisant la macro:

 #include  #define MAKE_A_FOO(I) class foo_##I \ { \ void print() \ { \ printf("%i", I); \ } \ }; MAKE_A_FOO(26) int main() { foo_26 f; f.print(); return 0; } 

Bien sûr, la version du modèle est un milliard de fois plus sûre et plus flexible.