Эффективный и современный С++. 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

Случай 1. >ParamType является указателем или ссылкой, но не универсальной ссылкой

Простейшая ситуация — когда >ParamType является ссылочным типом или типом указателя, но не универсальной ссылкой. В этом случае вывод типа работает следующим образом.

1. Если типом >expr является ссылка, ссылочная часть игнорируется.

2. Затем выполняется сопоставление типа >expr с >ParamType для определения . Например, если у нас имеются шаблон

>template

>void f(T& param); // param представляет собой ссылку

и объявления переменных

>int x = 27;        // x имеет тип int