Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 25
Скотт Мейерс
Однако у этого поведения есть следствия, о которых необходимо знать. В коде
int x = 0;
x
является именем переменной, так что decltype(x)
представляет собой int
. Однако “заворачивание” имени x
в скобки — “(x)
” — дает выражение, более сложное, чем имя. Будучи именем, x
представляет собой lvalue, и С++ также определяет выражение (x)
как lvalue. Следовательно, decltype((x))
представляет собой int&
. Добавление скобок вокруг имени может изменить тип, возвращаемый для него decltype
!
В C++11 это просто любопытный факт, но в сочетании с поддержкой в С++14 decltype (auto)
это означает, что, казалось бы, тривиальные изменения в способе записи инструкции return
могут повлиять на выводимый тип функции:
decltype(auto) f1() {
int x = 0;
…
return x; // decltype(x) представляет собой int,
} // так что f1 возвращает int
decltype(auto) f2() {
int x = 0;
…
return (x); // decltype((x)) представляет собой int&,
} // так что f2 возвращает int&
Обратите внимание, что f2
не только имеет возвращаемый тип, отличный от f1
, но и возвращает ссылку на локальную переменную! Этот код ведет вас к неопределенному поведению, что вряд ли является вашей целью.
Основной урок состоит в том, чтобы при использовании decltype(auto)
уделять деталям самое пристальное внимание. Кажущиеся совершенно незначительными детали в выражении, для которого выводится тип, могут существенно повлиять на тип, возвращаемый decltype(auto)
. Чтобы гарантировать, что выводимый тип — именно тот, который вы ожидаете, используйте методы, описанные в разделе 1.4.
В то же время не забывайте и о более широкой перспективе. Конечно, decltype
(как автономный, так и в сочетании с auto
) при выводе типов иногда может привести к сюрпризам, но это не нормальная ситуация. Как правило, decltype
возвращает тот тип, который вы ожидаете. Это особенно верно, когда decltype
применяется к именам, потому что в этом случае decltype
делает именно то, что скрывается в его названии: сообщает объявленный тип (
Следует запомнить
• decltype
почти всегда дает тип переменной или выражения без каких-либо изменений.
• Для lvalue-выражений типа Т
, отличных от имени, decltype
всегда дает тип T&
.
• C++14 поддерживает конструкцию decltype(auto)
, которая, подобно auto
, выводит тип из его инициализатора, но выполняет вывод типа с использованием правил decltype
.
1.4. Как просмотреть выведенные типы
Выбор инструментов для просмотра результатов вывода типа зависит от фазы процесса разработки программного обеспечения, на которой вы хотите получить эту информацию. Мы рассмотрим три возможности: получение информации о выводе типа при редактировании кода, во время компиляции и во время выполнения.
Редакторы IDE
Редакторы исходных текстов в IDE часто показывают типы программных сущностей (например, переменных, параметров, функций и т.п.), когда вы, например, помещаете указатель мыши над ними. Например, пусть у вас есть код