Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 19
и передадим ему массив
>f(name); // Передача массива функции f
то тип, выведенный для >Т
, будет в действительности типом массива! Этот тип включает размер массива, так что в нашем примере >Т
выводится как >const char[13]
, а типом параметра >f
(ссылки на этот массив) является >const char (&)[13]
. Да, выглядит этот синтаксис как наркотический бред, но знание его прибавит вам веса в глазах понимающих людей.
Интересно, что возможность объявлять ссылки на массивы позволяет создать шаблон, который выводит количество элементов, содержащихся в массиве:
>// Возвращает размер массива как константу времени компиляции.
>// Параметр не имеет имени, поскольку, кроме количества
>// содержащихся в нем элементов, нас ничто не интересует.
>template
>constexpr std::size_t arraySize(T (&)[N]) nоехсерt {
> return N;
>}
Как поясняется в разделе 3.9, объявление этой функции как >constexpr
делает ее результат доступным во время компиляции. Это позволяет объявить, например, массив с таким же количеством элементов, как и у второго массива, размер которого вычисляется из инициализатора в фигурных скобках:
>// keyVals содержит 7 элементов:
>int keyVals[] = { 1, 3, 7, 9, 11, 22, 35 };
>int mappedVals[arraySize(keyVals)]; // mappedVals - тоже
Конечно, как разработчик на современном С++ вы, естественно, предпочтете >std::array
встроенному массиву:
>// Размер mappedVals равен 7
>std::array
Что касается объявления >arraySize
как >noexcept
, то это помогает компилятору генерировать лучший код. Детальнее этот вопрос рассматривается в разделе 3.8.
Массивы — не единственные сущности в С++, которые могут превращаться в указатели. Типы функций могут превращаться в указатели на функции, и все, что мы говорили о выводе типов для массивов, применимо к выводу типов для функций и их преобразованию в указатели на функции. В результате получаем следующее:
>void someFunc(int, double); // someFunc - функция;
> // ее тип - void (int, double)
>template
>void f1(Т param); // В f1 param передается по значению
>template
>void f2(T& param); // В f2 param передается по ссылке
>f1(someFunc); // param выводится как указатель на
> // функцию; тип - void (*)(int, double)
>f2(someFunc); // param выводится как ссылка на
> // функцию; тип - void(&)(int,double)