Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 14
>auto
. Этот раздел содержит информацию, которую вы должны знать.Если вы готовы посмотреть сквозь пальцы на применение небольшого количества псевдокода, то можно рассматривать шаблон функции как имеющий следующий вид:
>template
>void(ParamType param);
Вызов может выглядеть следующим образом:
>f(expr); // Вызов f с некоторым выражением
В процессе компиляции компилятор использует expr для вывода двух типов: типа >Т
и типа >ParamType
. Эти типы зачастую различны, поскольку >ParamType
часто содержит “украшения”, например >const
или квалификаторы ссылки. Например, если шаблон объявлен как
>template
>void f(const T& param); // ParamType - const T&
и мы осуществляем вызов
>int x = 0;
>f(x); // Вызов f с параметром int
то >Т
выводится как >int
, а >ParamType
— как >const int&
.
Вполне естественно ожидать, что тип, выведенный для >Т
, тот же, что и тип переданного функции аргумента, т.е. что >Т
— это тип выражения >expr
. В приведенном выше примере это так: >x
— значение типа >int
и >Т
выводится как >int
. Но вывод не всегда работает таким образом. Тип, выведенный для >T
, зависит не только от типа >expr
, но и от вида >ParamType
. Существует три случая.
• >ParamType
представляет собой указатель или ссылку, но не универсальную ссылку. (Универсальные ссылки рассматриваются в разделе 5.2. Пока что все, что вам надо знать, — что они существуют и не являются ни ссылками lvalue, ни ссылками rvalue.)
• >ParamType
является универсальной ссылкой.
• >ParamType
не является ни указателем, ни ссылкой.
Следовательно, нам надо рассмотреть три сценария вывода. Каждый из них основан на нашем общем виде шаблонов и их вызова:
>template
>void f(ParamType param);
>f(expr); // Вывод Т и ParamType из expr
>ParamType
является указателем или ссылкой, но не универсальной ссылкойПростейшая ситуация — когда >ParamType
является ссылочным типом или типом указателя, но не универсальной ссылкой. В этом случае вывод типа работает следующим образом.
1. Если типом >expr
является ссылка, ссылочная часть игнорируется.
2. Затем выполняется сопоставление типа >expr
с >ParamType
для определения >Т
. Например, если у нас имеются шаблон
>template
>void f(T& param); // param представляет собой ссылку
и объявления переменных
>int x = 27; // x имеет тип int