111 votes

Ce n'modèle <unsigned int="" N=""> signifie?

Lors de la déclaration d'un modèle, je suis habitué à avoir ce genre de code:

template <class T>

Mais dans cette question, ils ont utilisé:

template <unsigned int N>

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

146voto

Oui, c'est un non-type de paramètre. Vous pouvez avoir plusieurs types de paramètres de modèle

  • Les Paramètres De Type.
    • Types
    • Les modèles (seules les classes, pas de fonctions)
  • Non les Paramètres de type
    • Les pointeurs
    • Références
    • Partie intégrante des expressions constantes

Ce que vous avez là est le dernier type. C'est un moment de la compilation constante (appelée constante de l'expression) et est de type entier ou une énumération. Après le recherchant dans la norme, j'ai dû déplacer modèles de classe dans la section types d' - même si les modèles ne sont pas les types. Mais ils sont appelés par type de paramètres dans le but de décrire ces sortes néanmoins. Vous pouvez avoir des pointeurs (et également membre des pointeurs) et des références à des objets/fonctions qui ont une liaison externe (ceux qui peuvent être liés à d'autres fichiers de l'objet, et dont l'adresse est unique dans l'ensemble du programme). Exemples:

Modèle type de paramètre:

template<typename T>
struct Container {
    T t;
};

// pass type "long" as argument.
Container<long> test;

Modèle de paramètre de type entier:

template<unsigned int S>
struct Vector {
    unsigned char bytes[S];
};

// pass 3 as argument.
Vector<3> test;

Modèle de pointeur de paramètre (passage d'un pointeur à une fonction)

template<void (*F)()>
struct FunctionWrapper {
    static void call_it() { F(); }
};

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

Modèle de paramètre de référence (passage d'un entier)

template<int &A>
struct SillyExample {
    static void do_it() { A = 10; }
};

// pass flag as argument
int flag;
SillyExample<flag> test;

Modèle de paramètre du modèle.

template<template<typename T> class AllocatePolicy>
struct Pool {
    void allocate(size_t n) {
        int *p = AllocatePolicy<int>::allocate(n);
    }
};

// pass the template "allocator" as argument. 
template<typename T>
struct allocator { static T * allocate(size_t n) { return 0; } };
Pool<allocator> test;

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

template<unsigned int SIZE = 3>
struct Vector {
    unsigned char buffer[SIZE];
};

Vector<> test;

Du point de vue syntaxique, template<> est réservé à une marque explicite d'une spécialisation de modèle, au lieu d'un modèle sans paramètres:

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

139voto

Andy Points 3471

Il est parfaitement possible à un modèle de classe sur un entier plutôt qu'un type. Nous pouvons attribuer l'basées sur des modèles de valeur à une variable, ou manipuler d'une manière que nous puissions, avec toute autre littéral entier:

unsigned int x = N;

En fait, nous pouvons créer des algorithmes qui permettent d'évaluer au moment de la compilation (de Wikipedia):

template <int N>
struct Factorial 
{
     enum { value = N * Factorial<N - 1>::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
}

15voto

Loki Astari Points 116129

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

Exemple:

template <unsigned int N>
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.
 }

13voto

Jonathan Points 61

Un modèle de classe est comme une macro, seule en beaucoup moins mal.

Pensez à un modèle sous la forme d'une macro. Les paramètres pour le modèle get substitué dans une classe (ou une fonction) définition, lorsque vous définissez une classe (ou une fonction) à l'aide d'un modèle.

La différence est que les paramètres ont des "types" et les valeurs transmises sont vérifiées lors de la compilation, comme les paramètres de fonctions. Les types valides sont régulièrement vos types C++, comme int et char. Lors de l'instanciation d'une classe de modèle, vous transmettez une valeur du type que vous avez spécifié, et dans une nouvelle copie de la classe de modèle de définition de cette valeur se substituer dans tous les cas où le nom du paramètre a dans la définition d'origine. Tout comme une macro.

Vous pouvez également utiliser la fonction "class" ou "typename" types de paramètres (ils sont vraiment la même chose). Avec un paramètre de l'un de ces types, vous pouvez passer d'un type de nom au lieu d'une valeur. Tout comme avant, partout le nom du paramètre a dans le modèle de définition de la classe, dès que vous créez une nouvelle instance, devient quel que soit le type que vous transmettre. 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érer cette classe de modèle exemple de code:

#include <cstdio>
template <int I>
class foo
{
  void print()
  {
    printf("%i", I);
  }
};

int main()
{
  foo<26> f;
  f.print();
  return 0;
}

Il est fonctionnellement le même que celui de la macro à l'aide de code:

#include <cstdio>
#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ûr et plus souple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X