Ответ 1
Пересылка типа возвращаемого типа в общем коде
Для не общего кода, как и в предыдущем примере, вы можете вручную выбрать, чтобы получить ссылку как возвращаемый тип:
auto const& Example(int const& i)
{
return i;
}
но в общем коде вы хотите иметь возможность отлично перенаправлять тип возврата, не зная, имеете ли вы дело со ссылкой или значением. decltype(auto)
дает вам эту способность:
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
Отложенный возврат типа возврата в рекурсивных шаблонах
В этом Q & A несколько дней назад была обнаружена бесконечная рекурсия во время создания шаблона, когда возвращаемый тип шаблона был указанный как decltype(iter(Int<i-1>{}))
вместо decltype(auto)
.
template<int i>
struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto)
{ return iter(Int<i-1>{}); }
int main() { decltype(iter(Int<10>{})) a; }
decltype(auto)
используется здесь для задержки вывода возвращаемого типа после того, как пыль шаблона была установлена.
Другие использования
Вы также можете использовать decltype(auto)
в других контекстах, например. в проекте стандарта N3936 также указано
7.1.6.4 автоопределение [dcl.spec.auto]
1 Спецификации типа
auto
иdecltype(auto)
обозначают местозаполнитель тип, который будет заменен позже, либо путем вычитания из инициализатор или явным определением с типом возвращаемого типа. Тип типаauto
также используется для обозначения того, что лямбда является общая лямбда.2 Тип заполнителя может отображаться с помощью декларатора функции в описании-specifier-seq, type-specifier-seq, convert-function-id или trailing-return-type, в любом контексте, где такой декларатор действителен. Если функция declarator включает в себя тип trailing-return-type (8.3.5), который задает объявленный тип возвращаемого значения функции. Если объявленный тип возвращаемой функции содержит тип заполнителя, возвращаемый тип функции выводится из операторов возврата в теле функции, если таковая имеется.
Проект также содержит этот пример инициализации переменной:
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(auto) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype(auto) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(auto) x5d = f(); // decltype(x5d) is int&&
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i; // decltype(x7a) is int*
decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)