В c ++ 14 decltype(auto)
введена идиома.
Обычно его используют для того, чтобы auto
объявления могли использовать decltype
правила для данного выражения .
В поисках примеров «хорошего» использования идиомы я могу думать только о таких вещах, как ( Скотт Мейерс ), а именно о выводе типа возвращаемого значения функции :
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Есть ли другие примеры, где эта новая языковая функция полезна?
decltype(auto)
что-то похожееtemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, хотя потом понял, что должен был использовать,return (p.first);
что удивительно работает (но IIRC это даже задумано).decltype(auto)
может привести к тому, что что-то будет скопировано / перемещено в объявленный объект, вопреки ожиданиям.Ответы:
Переадресация типа возврата в универсальном коде
Для неуниверсального кода, как и в приведенном вами примере, вы можете вручную выбрать ссылку в качестве типа возврата:
но в общем коде вы хотите иметь возможность полностью пересылать возвращаемый тип, не зная, имеете ли вы дело со ссылкой или значением.
decltype(auto)
дает вам эту способность:Задержка вывода типа возврата в рекурсивных шаблонах
В этих вопросах и ответах несколько дней назад возникла бесконечная рекурсия во время создания шаблона, когда тип возврата шаблона был указан
decltype(iter(Int<i-1>{}))
вместоdecltype(auto)
.decltype(auto)
используется здесь для отсрочки вычета типа возврата после того, как пыль от создания экземпляра шаблона исчерпана.Другое использование
Вы также можете использовать
decltype(auto)
в других контекстах, например, в проекте стандарта N3936 также говорится7.1.6.4 автоматический спецификатор [dcl.spec.auto]
Черновик также содержит этот пример инициализации переменной:
источник
(i)
противi
новой вещи в C ++ 14?decltype(expr)
иdecltype((expr))
уже отличаются в C ++ 11, это обобщает это поведение.auto
задача также справилась бы с задачей, так как результат все равно возвращается по значению ... Или я пропустил что-то?Цитирую материал отсюда :
decltype(auto)
прежде всего полезен для определения возвращаемого типа функций пересылки и аналогичных оболочек , где вы хотите, чтобы тип точно «отслеживал» некоторое выражение, которое вы вызываете.Например, учитывая функции ниже:
Тем
decltype(auto)
не менее, он не предназначен для того, чтобы широко использоваться за его пределами.В частности, хотя его можно использовать для объявления локальных переменных , это, вероятно, просто антипаттерн, поскольку ссылка на локальную переменную не должна зависеть от выражения инициализации.
Кроме того, он чувствителен к тому, как вы пишете инструкцию возврата.
Например, две функции ниже имеют разные типы возврата:
string
, второе возвращаетstring&
, которое является ссылкой на локальную переменнуюstr
.Из предложения вы можете увидеть больше предполагаемого использования.
источник
auto
для возврата?auto
возвратом), но ОП специально спрашивал об использованииdecltype(auto)
.auto lookup_a_string() { ... }
? Это всегда не ссылочный тип? И поэтомуauto lookup_a_string() ->decltype(auto) { ... }
необходимо принудительно разрешить возврат (в некоторых случаях) ссылок?auto
определяется в терминах шаблона передачи по значению, поэтому да, он не может быть ссылкой. Пожалуйста, подождите,auto
может быть что угодно, включая ссылку, конечно.std::vector
. Скажи, что у тебя естьtemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. ЗатемS<bool>::operator[]
вернет свисающие ссылки из-за специализацииstd::vector<bool>
. Изменение типа возвращаемого значения позволяетdecltype(auto)
обойти эту проблему.