web-dev-qa-db-fra.com

Quelqu'un peut-il expliquer ce code de modèle qui me donne la taille d'un tableau?

template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
    return n;
}

La partie que je ne reçois pas est les paramètres de cette fonction de modèle. Que se passe-t-il avec le tableau lorsque je passe là-bas qui donne n comme nombre d'éléments dans le tableau?

62
marsol0x

Eh bien, vous devez d'abord comprendre que tenter d'obtenir une valeur d'un tableau peut vous donner un pointeur à son premier élément:

int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost

Les références font référence à des objets à l'aide de leur type exact ou de leur type de classe de base. La clé est que le modèle prend des tableaux par référence. Les tableaux (ne se référennent pas à eux) car les paramètres n'existent pas en C++. Si vous donnez un paramètre un type de tableau, ce sera un pointeur à la place. Ainsi, en utilisant une référence est nécessaire lorsque nous voulons connaître la taille de la matrice transmise. La taille et le type d'élément sont automatiquement déduites, comme c'est généralement le cas pour les modèles de fonctions. Le modèle suivant

template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
    return n;
}

Appelé avec notre tableau précédemment défini a instantiez implicitement la fonction suivante:

size_t array_size(const int (&)[3]) {
    return 3;
}

Qui peut être utilisé comme ceci:

size_t size_of_a = array_size(a);

Il y a une variation que j'ai faite il y a quelque temps [EDIT: Il s'agit de quelqu'un déjà eu la même idée ici ] qui peut déterminer une valeur au moment de la compilation. Au lieu de renvoyer la valeur directement, il donne au gabarit un type de retour en fonction de n:

template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];

Vous dites si le tableau a n éléments, le type de retour est une référence à une matrice ayant la taille n et type d'élément char. Maintenant, vous pouvez obtenir une taille déterminée de la compilation de la matrice transmise:

size_t size_of_a = sizeof(array_size(a));

Parce qu'un tableau de char ayant n éléments a la taille de n, qui vous donnera également le nombre d'éléments dans la matrice donnée également. Au moment de la compilation, vous pouvez donc faire

int havingSameSize[sizeof(array_size(a))];

Étant donné que la fonction n'est jamais appelée, il n'a pas besoin d'être défini, de sorte qu'il n'a pas de corps. J'espère pouvoir effacer un peu la question.

88

Pensez-y de cette façon, supposons que vous ayez eu un tas de fonctions:

// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
    return 1;
}

size_t array_size(const int (&)[2])
{
    return 2;
}

size_t array_size(const int (&)[3])
{
    return 3;
}
// etc...

Maintenant, lorsque vous appelez cela, quelle fonction est appelée?

int a[2];
array_size(a);  

Maintenant, si vous templissez la faille, vous obtenez:

template <int n>
size_t array_size(const int (&)[n])
{
    return n;
}

Le compilateur tentera d'instancier une version de Array_Size qui correspond à tout paramètre avec lequel vous l'appelez. Donc, si vous l'appelez avec un tableau de 10 INTS, cela instancera Array_Size avec N = 10.

Ensuite, il suffit de templatiser le type, vous pouvez donc l'appeler avec plus que des tableaux d'intensité:

template <typename T, int n>
size_t array_size(const T (&)[n])
{
    return n;
}

Et tu as fini.

éditer: une note sur le (&)

Les parenthèses sont nécessaires autour de la & Pour différencier l'ensemble des références internationales (illégales) et référence au tableau d'INT (ce que vous voulez). Depuis la priorité de [] est plus élevé que &, si vous avez la déclaration:

const int &a[1];

en raison de la priorité de l'opérateur, vous vous retrouvez avec une gamme d'un élément des références constantes à l'INT. Si vous voulez le & Appliqué d'abord, vous devez forcer cela avec des parenthèses:

const int (&a)[1];  

Maintenant, vous avez une référence de const à un ensemble d'INTS. Dans la liste des paramètres de fonction, vous n'avez pas besoin de spécifier le nom d'un paramètre si vous ne l'utilisez pas, vous pouvez donc laisser tomber le nom, mais garder les parenthèses:

size_t array_size(const int (&)[1])
21
Eclipse

Rien n'arrive à la matrice. C'est un paramètre inutilisé utilisé pour résoudre la signature de la fonction de modèle.

Il ne peut également pas être utilisé comme argument de modèle, mais c'est une NIT séparée.

1
MSN