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



>const int cx = x;  // cx имеет тип const int

>const int& rx = x; // rx является ссылкой на x как на const int

то выводимые типы для >param и в различных выводах будут следующими:

>f(x);  // Т - int, тип param - int&

>f(cx); // Т - const int, тип param - const int&

>f(rx); // Т - const int, тип param - const int&

Во втором и третьем вызовах обратите внимание, что, поскольку >cx и >rx объявлены как константные значения, выводится как >const int тем самым приводя к типу параметра >const int&. Это важно для вызывающего кода. Передавая константный объект параметру-ссылке, он ожидает, что объект останется неизменным, т.е. что параметр будет представлять собой ссылку на >const. Вот почему передача константного объекта в шаблон, получающий параметр >T&, безопасна: константность объекта становится частью выведенного для типа.

В третьем примере обратите внимание, что несмотря на то, что типом >rx является ссылка, тип >T выводится как не ссылочный. Вот почему при выводе типа игнорируется “ссылочность” >rx.

Все эти примеры показывают ссылочные параметры, являющиеся lvalue, но вывод типа точно так же работает и для ссылочных параметров rvalue. Конечно, аргументы могут передаваться только ссылочным параметрам, являющимся rvalue, но это ограничение никак не влияет на вывод типов.

Если мы изменим тип параметра >f с >Т& на >const Т&, произойдут небольшие изменения, но ничего удивительного не случится. Константность >cx и >rx продолжает соблюдаться, но поскольку теперь мы считаем, что >param является ссылкой на >const, >const как часть выводимого типа >T не требуется:

>template

>void f(const T& param); // param является ссылкой на const


>int x = 27;             // Как и ранее

>const int cx = x;       // Как и ранее

>const int& rx = x;      // Как и ранее


>f(x);                   // Т - int, тип param - const int&

>f(cx);                  // Т - int, тип param - const int&

>f(rx);                  // Т - int, тип param - const int&

Как и ранее, “ссылочность” >rx при выводе типа игнорируется.

Если бы >param был указателем (или указателем на >const), а не ссылкой, все бы работало, по сути, точно так же:

>template

>void f(T* param);   // Теперь param является указателем


>int x = 27;         // Как и ранее

>const int *px = &x; // px - указатель на x, как на const int


>f(&x);              // Т - int, тип param - int*

>f(px);              // Т - const int, тип param - const int*

Сейчас вы можете обнаружить, что давно усердно зеваете, потому что все это очень скучно, правила вывода типов в С++ работают так естественно для ссылок и указателей, что все просто очевидно! Это именно то, что вы хотите от системы вывода типов.