D'abord, disséquons le paramètre, T(&)[size]
. Lisez les déclarations de l'intérieur vers l'extérieur, de droite à gauche, le groupe de parenthèses en premier : C'est un paramètre sans nom qui est une référence à un tableau de taille size
de type T
.
C'est-à-dire qu'il accepte une référence à un tableau quelconque, où le type et la taille du tableau sont des paramètres de modèle.
Si on l'appelle comme ça :
int a[10];
GetArrLength(a);
Le compilateur essaiera de déduire les paramètres du modèle. Pour que le type de paramètre corresponde à ce que vous passez, T
doit être int
y size
doit être 10 (ce qui fait du paramètre une référence à un tableau de 10 int
s).
Vous retournez ensuite cette taille, ce qui vous donne le nombre d'éléments dans un tableau.
Il y a deux "problèmes" avec ce code. Premièrement, les tailles ne peuvent pas être négatives, il n'est donc pas logique d'utiliser un type signé comme paramètre du modèle et comme type de retour. Il convient plutôt d'utiliser un type non signé ; le meilleur serait std::size_t
:
template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }
La seconde est que le résultat de cette fonction n'est pas une expression constante, même si la taille d'un tableau l'est. Bien que cela convienne dans la plupart des situations, il serait préférable de pouvoir en tirer une expression constante. C'est ainsi que l'on aboutit à cette solution :
template <std::size_t N>
struct type_of_size
{
typedef char type[N];
};
template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);
#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))
Il est utilisé comme tel :
int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!
Il fonctionne de trois façons : la première est la même idée que ci-dessus, à savoir que les paramètres du modèle seront remplis pour vous donner la taille du tableau.
La deuxième partie consiste à utiliser ces informations pour fabriquer un type de taille spécifique, d'où l'appellation de " type ". type_of_size
aide. Cette partie n'est pas strictement nécessaire, mais je pense qu'elle rend le code plus facile à lire. A char[N]
a une taille égale à N
toujours, et nous pouvons donc en abuser pour "stocker" la taille du tableau... dans la taille d'un fichier type lui-même !
La troisième partie consiste à obtenir cette taille avec sizeof
. Elle n'évalue rien, et nous n'avons donc pas besoin d'une définition de la fonction. Elle dit simplement "Si vous faisiez ceci... la taille serait de...". Et la taille est notre taille "stockée", dans le format char
le tableau.