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



Это редко приводит к каким-то отличиям на практике, но если вы знаете о преобразовании массивов в указатели, то разберетесь и в преобразовании функций в указатели.

Итак, у нас есть правила для вывода типов шаблонов, связанные с >auto. В начале я заметил, что они достаточно просты, и по большей части так оно и есть. Немного усложняет жизнь отдельное рассмотрение согласованных lvalue при выводе типов для универсальных ссылок, да еще несколько “мутят воду” правила преобразования в указатели для массивов и функций. Иногда так и хочется, разозлившись, схватить компилятор и вытрясти из него — “А скажи-ка, любезный, какой же тип ты выводишь?” Когда это произойдет, обратитесь к разделу 1.4, поскольку он посвящен тому, как уговорить компилятор это сделать.

Следует запомнить

• В процессе вывода типа шаблона аргументы, являющиеся ссылками, рассматриваются как ссылками не являющиеся, т.е. их “ссылочность” игнорируется.

• При выводе типов для параметров, являющихся универсальными ссылками, lvalue-apгумeнты рассматриваются специальным образом.

• При выводе типов для параметров, передаваемых по значению, аргументы, объявленные как >const и/или >volatile, рассматриваются как не являющиеся ни >const, ни >volatile.

• В процессе вывода типа шаблона аргументы, являющиеся именами массивов или функций, преобразуются в указатели, если только они не использованы для инициализации ссылок.

1.2. Вывод типа >auto

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

Да, это так, но это не имеет значения. Существует прямая взаимосвязь между выводом типа шаблона и выводом типа >auto. Существует буквальное алгоритмическое преобразование одного в другой.

В разделе 1.1 вывод типа шаблона пояснялся с использованием обобщенного шаблона функции

>templateТ>

>void f(ParamType param);

и обобщенного вызова

>f(expr); // Вызов f с некоторым выражением

При вызове >f компиляторы используют >expr для вывода типов >T и >ParamType.

Когда переменная объявлена с использованием ключевого слова >auto, оно играет роль в шаблоне, а спецификатор типа переменной действует как >ParamType. Это проще показать, чем описать, так что рассмотрим следующий пример: