Читать «Эффективный и современный С++. 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 делает именно то, что скрывается в его названии: сообщает объявленный тип (declared type) имени.

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

• decltype почти всегда дает тип переменной или выражения без каких-либо изменений.

• Для lvalue-выражений типа Т, отличных от имени, decltype всегда дает тип T&.

• C++14 поддерживает конструкцию decltype(auto), которая, подобно auto, выводит тип из его инициализатора, но выполняет вывод типа с использованием правил decltype.

1.4. Как просмотреть выведенные типы

Выбор инструментов для просмотра результатов вывода типа зависит от фазы процесса разработки программного обеспечения, на которой вы хотите получить эту информацию. Мы рассмотрим три возможности: получение информации о выводе типа при редактировании кода, во время компиляции и во время выполнения.

Редакторы IDE

Редакторы исходных текстов в IDE часто показывают типы программных сущностей (например, переменных, параметров, функций и т.п.), когда вы, например, помещаете указатель мыши над ними. Например, пусть у вас есть код