Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 | страница 27
>decltype
и>auto
?), в действительности имеет смысл: >auto
указывает, что тип должен быть выведен, а >decltype
говорит о том, что в процессе вывода следует использовать правила >decltype
. Итак, можно записать >authAndAccess
следующим образом:>template
>decltype(auto) // но все еще
>authAndAccess(Containers с, Index i) // требует
>{ // уточнения
> authenticateUser();
> return c[i];
>}
Теперь >authAndAccess
действительно возвращает то же, что и >c[i]
. В частности, в распространенном случае, когда >c[i]
возвращает >Т&
, >authAndAccess
также возвращает >Т&
, и в том редком случае, когда >c[i]
возвращает объект, >authAndAccess
также возвращает объект.
Использование >decltype(auto)
не ограничивается возвращаемыми типами функций. Это также может быть удобно для объявления переменных, когда вы хотите применять правила вывода типа >decltype
к инициализирующему выражению:
>Widget w;
>const Widget& cw = w;
>auto myWidget1 = cw; // Вывод типа auto:
> // тип myWidget1 - Widget
>decltype(auto) myWidget2 = cw; // Вывод типа decltype:
> // тип myWidget2 - const Widget&
Я знаю, что вас беспокоят два момента. Один из них — упомянутое выше, но пока не описанное уточнение >authAndAccess
. Давайте, наконец-то, разберемся в этом вопросе. Еще раз посмотрим на версию >authAndAccess
в С++14:
>template
>decltype(auto) authAndAccess(Container& с, Index i);
Контейнер передается как lvalue-ссылка на неконстантный объект, поскольку возвращаемая ссылка на элемент контейнера позволяет клиенту модифицировать этот контейнер. Но это означает, что этой функции невозможно передавать контейнеры, являющиеся rvalue. rvalue невозможно связать с lvalue-ссылками (если только они не являются lvalue-ссылками на константные объекты, что в данном случае очевидным образом не выполняется).
Надо сказать, что передача контейнера, являющегося rvalue, в >authAndAccess
является крайним случаем. Такой rvalue-контейнер, будучи временным объектом, обычно уничтожается в конце инструкции, содержащей вызов >authAndAccess
, а это означает, что ссылка на элемент в таком контейнере (то, что должна вернуть функция >authAndAccess
) окажется “висячей” в конце создавшей ее инструкции. Тем не менее передача временного объекта функции