Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 21



>auto x = 27;

Здесь спецификатором типа для >x является >auto само по себе. С другой стороны, в объявлении

>const auto cx = x;

спецификатором типа является >const auto. А в объявлении

>const auto& rx = x;

спецификатором типа является >const auto&. Для вывода типов для >x, >сх и >rx в приведенных примерах компилятор действует так, как если бы для каждого объявления имелся шаблон, а также вызов этого шаблона с соответствующим инициализирующим выражением:

>template              // Концептуальный шаблон для

>void func_for_x(Т param);         // вывода типа x


>func_for_x(27);                   // Концептуальный вызов: выве-

>                                  // денный тип param является

>                                  // типом x


>template              // Концептуальный шаблон для

>void func_for_cx(const Т param);  // вывода типа cx


>func_for_cx(x);                   // Концептуальный вызов: выве-

>                                  // денный тип param является

>                                  // типом cx


>template              // Концептуальный шаблон для

>void func_for_rx(const T& param); // вывода типа rx


>func_for_rx(x);                   // Концептуальный вызов: выве-

>                                  // денный тип param является

>                                  // типом rx

Как я уже говорил, вывод типов для >auto представляет собой (с одним исключением, которое мы вскоре рассмотрим) то же самое, что и вывод типов для шаблонов.

В разделе 1.1 вывод типов шаблонов был разделен на три случая, основанных на характеристиках >ParamType, спецификаторе типа >param в обобщенном шаблоне функции. В объявлении переменной с использованием >auto спецификатор типа занимает место >ParamType, так что у нас опять имеются три случая.

• Случай 1. Спецификатор типа представляет собой ссылку или указатель, но не универсальную ссылку.

• Случай 2. Спецификатор типа представляет собой универсальную ссылку.

• Случай 3. Спецификатор типа не является ни ссылкой, ни указателем. Мы уже встречались со случаями 1 и 3:

>auto x = 27;        // Случай 3 (x не указатель и не ссылка)

>const auto cx = x;  // Случай 3 (cx не указатель и не ссылка)

>const auto& rx = x; // Случай 1 (rx - неуниверсальная ссылка)

Случай 2 работает, как и ожидалось:

>auto&& uref1 = x;  // x - int и lvalue, так что тип uref1 – int&

>auto&& uref2 = cx; // cx - const int и lvalue, так что тип

>                   // uref2 - const int&

>auto&& uref3 = 27; // 27 - int и rvalue, так что тип