Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 29
>template
>auto // версия для
>authAndAccess(Container&& с, Index i) // C++11
> -> decltype(std::forward
> authenticateUser();
> return std::forward
>}
Вторым беспокоящим моментом является мое замечание в начале этого раздела о том, что >decltype
почти всегда дает тип, который вы ожидаете, т.е. что он редко преподносит сюрпризы. По правде говоря, вряд ли вы столкнетесь с этими исключениями из правила, если только вы не занимаетесь круглосуточно написанием библиотек.
Чтобы полностью понимать поведение >decltype
, вы должны познакомиться с некоторыми особыми случаями. Большинство из них слишком невразумительны, чтобы быть размещенными в этой книге, но один из них приводит к лучшему пониманию >decltype
и его применения.
Применение >decltype
к имени дает объявленный тип для этого имени. Имена представляют собой lvalue-выражения, но это не влияет на поведение >decltype
. Однако для lvalue-выражений, более сложных, чем имена, >decltype
гарантирует, что возвращаемый тип всегда будет lvalue-ссылкой. Иначе говоря, если lvalue-выражение, отличное от имени, имеет тип >Т
, то >decltype
сообщает об этом типе как об >Т&
. Это редко на что-то влияет, поскольку тип большинства lvalue-выражений в обязательном порядке включает квалификатор lvalue-ссылки. Например, функции, возвращающие lvalue, всегда возвращают lvalue-ссылки.
Однако у этого поведения есть следствия, о которых необходимо знать. В коде
>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&
Обратите внимание, что