Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 17
Скотт Мейерс
void f1(Т param); // В f1 param передается по значению
template<typename Т>
void f2(T& param); // В f2 param передается по ссылке
f1(someFunc); // param выводится как указатель на
// функцию; тип - void (*)(int, double)
f2(someFunc); // param выводится как ссылка на
// функцию; тип - void(&)(int,double)
Это редко приводит к каким-то отличиям на практике, но если вы знаете о преобразовании массивов в указатели, то разберетесь и в преобразовании функций в указатели.
Итак, у нас есть правила для вывода типов шаблонов, связанные с auto
. В начале я заметил, что они достаточно просты, и по большей части так оно и есть. Немного усложняет жизнь отдельное рассмотрение согласованных lvalue при выводе типов для универсальных ссылок, да еще несколько “мутят воду” правила преобразования в указатели для массивов и функций. Иногда так и хочется, разозлившись, схватить компилятор и вытрясти из него — “А скажи-ка, любезный, какой же тип ты выводишь?” Когда это произойдет, обратитесь к разделу 1.4, поскольку он посвящен тому, как уговорить компилятор это сделать.
Следует запомнить
• В процессе вывода типа шаблона аргументы, являющиеся ссылками, рассматриваются как ссылками не являющиеся, т.е. их “ссылочность” игнорируется.
• При выводе типов для параметров, являющихся универсальными ссылками, lvalue-apгумeнты рассматриваются специальным образом.
• При выводе типов для параметров, передаваемых по значению, аргументы, объявленные как const
и/или volatile
, рассматриваются как не являющиеся ни const
, ни volatile
.
• В процессе вывода типа шаблона аргументы, являющиеся именами массивов или функций, преобразуются в указатели, если только они не использованы для инициализации ссылок.
1.2. Вывод типа auto
Если вы прочли раздел 1.1 о выводе типов шаблонов, вы знаете почти все, что следует знать о выводе типа auto
, поскольку за одним любопытным исключением вывод типа auto
auto
не имеет дела ни с одной из этих сущностей.
Да, это так, но это не имеет значения. Существует прямая взаимосвязь между выводом типа шаблона и выводом типа auto
. Существует буквальное алгоритмическое преобразование одного в другой.
В разделе 1.1 вывод типа шаблона пояснялся с использованием обобщенного шаблона функции
template<typename Т>
void f(
и обобщенного вызова
f(
При вызове f
компиляторы используют expr
для вывода типов T
и ParamType
.
Когда переменная объявлена с использованием ключевого слова auto
, оно играет роль Т
в шаблоне, а спецификатор типа переменной действует как ParamType
. Это проще показать, чем описать, так что рассмотрим следующий пример:
auto x = 27;
Здесь спецификатором типа для x
является auto
само по себе. С другой стороны, в объявлении
const auto cx = x;
спецификатором типа является const auto
. А в объявлении