Alguém pode explicar esse código de modelo que me dá o tamanho de uma matriz?

template size_t array_size(const T (&)[n]) { return n; } 

A parte que eu não entendo são os parâmetros para esta function de template. O que acontece com o array quando eu passo por lá que dá n como o número de elementos no array?

    Bem, primeiro você tem que entender que tentar obter um valor fora de uma matriz pode lhe dar um ponteiro para o primeiro elemento:

     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 

    Referências referem-se a objects usando o tipo exato ou o tipo de class base. A chave é que o modelo usa matrizes por referência. Arrays (não referências a eles) como parâmetros não existem em C ++. Se você der a um parâmetro um tipo de matriz, ele será um ponteiro. Então, usar uma referência é necessário quando queremos saber o tamanho da matriz passada. O tamanho e o tipo de elemento são automaticamente deduzidos, como é geralmente o caso dos modelos de function. O modelo a seguir

     template size_t array_size(const T (&)[n]) { return n; } 

    Chamado com nosso array previamente definido, irá implicitamente instanciar a seguinte function:

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

    Que pode ser usado assim:

     size_t size_of_a = array_size(a); 

    Há uma variação que fiz há algum tempo atrás [Edit: Acontece que alguém já teve a mesma idéia aqui ], que pode determinar um valor em tempo de compilation. Em vez de retornar o valor diretamente, ele fornece ao modelo um tipo de retorno, dependendo de n :

     template char (& array_size(const T (&)[n]) )[n]; 

    Você diz que se a matriz tiver n elementos, o tipo de retorno é uma referência a uma matriz com tamanho n e tipo de elemento char . Agora, você pode obter um tamanho determinado em tempo de compilation da matriz passada:

     size_t size_of_a = sizeof(array_size(a)); 

    Como uma matriz de char com n elementos possui sizeof, isso também lhe dará o número de elementos na matriz especificada. Em tempo de compilation, você pode fazer

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

    Como a function nunca é realmente chamada, ela não precisa ser definida, portanto ela não possui um corpo. Espero que eu possa esclarecer o assunto um pouco.

    Pense nisso desta maneira, suponha que você tenha um monte de funções:

     // 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... 

    Agora, quando você chama isso, qual function é chamada?

     int a[2]; array_size(a); 

    Agora, se você templatizar o arraysize, você obtém:

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

    O compilador tentará instanciar uma versão de array_size que corresponda a qualquer parâmetro com o qual você o chame. Então, se você chamá-lo com uma matriz de 10 ints, ele irá instanciar array_size com n = 10.

    Em seguida, apenas templatize o tipo, para que você possa chamá-lo com mais do que apenas arrays int:

     template  size_t array_size(const T (&)[n]) { return n; } 

    E pronto.

    Edit : Uma nota sobre o (&)

    Os parênteses são necessários em torno do & para diferenciar entre a matriz de referências int (ilegal) e a referência para a matriz de ints (o que você deseja). Como a precedência de [] é maior que & , se você tiver a declaração:

     const int &a[1]; 

    por causa da precedência do operador, você acaba com uma matriz de um elemento de referências const para int. Se você quer o & aplicado primeiro, você precisa forçar isso com parênteses:

     const int (&a)[1]; 

    Agora você tem uma referência const a uma matriz de elementos de um elemento. Na lista de parâmetros da function, você não precisa especificar o nome de um parâmetro se não usá-lo, então você pode soltar o nome, mas manter os parênteses:

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

    Nada acontece com o array. É um parâmetro não utilizado que é usado para resolver a assinatura da function de modelo.

    Também não pode ser usado como um argumento de modelo, mas isso é um nit separado.

    Uma maneira estranha de obter o resultado como const de tempo de compilation para aqueles que não têm “constexpr”:

     #include  namespace { template  struct helper { enum { value = V }; }; template auto get_size(T(&)[Size]) -> helper < Size > { return helper < Size >() ; } template struct get_value { enum { value = T::value }; }; } int main() { std::cout < < get_value::value; }