Já aconteceu de escrever algo assim?
int arr[] = {1, 2, 3, 4, 5};
some_function( arr, sizeof(arr)/sizeof(arr[0]) );
Aqui, o tamanho do array é detectado pelo compilador porque ele possui uma lista de valores em sua inicialização. Mas some_function
quer saber seu tamanho, então o obtemos dividindo o tamanho do array pelo tamanho de seus elementos. Bastante longo.
Se for C ++, não C, podemos usar o poder dos modelos neste caso:
template<size_t SIZE, class T> inline size_t array_size(T (&arr)[SIZE]) {
return SIZE;
}
Outro recurso do C ++ também é usado aqui: referência de array. Quando uma função tem um argumento int (&a)[10]
, significa que ela só aceitará int
arrays de tamanho 10. Mas aqui o tipo T
e o tamanho SIZE
são parâmetros de modelo, então temos o processo inverso: ao invés de checar dado array com estes parâmetros T
e SIZE
(como eles são desconhecidos ), o compilador infere esses parâmetros de um determinado argumento. Dado tal array_size
definido, a chamada para some_function
pode ser reescrita assim:
int arr[] = {1, 2, 3, 4, 5};
some_function( arr, array_size(arr) );
Nesse caso, ao compilar a chamada para array_size
, o compilador estima que T
deve ser int
e SIZE
deve ser 5, pois é possível passar arr
apenas para . Na medida em que e forem inferidos de forma inequívoca, podem ser omitidos.array_size<5, int>
T
SIZE
<5, int>
Finalmente, você vê que é muito mais curto e mais claro (mais importante) do que a sizeof
variante!