Это способ получения размера параметра массива. Массивы имеют тип T[N]
, который часто может уменьшаться до T*
.
#include <iostream>
template <int N>
void foo(const char(&str)[N]){
for(int i=0;i<N;++i)
std::cout<<str<<' ';
}
void foo(const char* str){
//for(int i=0;i<??;++i)
}
void bar(const char* str, int n){
for(int i=0;i<n;++i)
std::cout<<str<<' ';
}
int main(){
const char str[] = "Hello";//type is const char[6]
const char* str2 = str; //Decay
// const char str3[] = str; (6)
int n = sizeof(str)/sizeof(str[0]);
foo(str);// (1) Calls foo<6>
foo(str2);// (2) Must call foo(const char*) which is useless
bar(str, n); // (3) Array can decay
bar(str2, n); // (4) Same as (3) - bar can be used with all arrays
bar(str2, 10); // (5) Buffer overrun
}
Приведенный выше пример показывает использование и ограничение шаблонного подхода. Преимущество заключается в том, что вам не нужно передавать размер отдельно, поэтому он всегда будет правильным. Большим недостатком является то, что процесс затухания необратим, поэтому функция становится бесполезной - (2) не может вызвать шаблон.
Шаблон удобен, но большинство массивов довольно быстро распадаются на указатели, передавая их через bar
- что было единственным способом в C - или просто потому, что их размер неизвестен во время компиляции - malloc, new
. Другая проблема заключается в том, что и в C, и в C ++ (6) недопустимо - не существует неявного способа копирования массива. Таким образом, подход bar
встречается гораздо чаще, но для получения правильного размера требуется дополнительная осторожность. Правильный способ c ++ - использовать std::vector
или std::array
, если только они не являются узким местом.