Переадресація повернення типу в загальному коді
Для негенеричного коду, як початковий приклад, який ви подали, ви можете вручну вибрати, щоб отримати посилання як тип повернення:
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)...);
}
Затримка вирахування типу повернення в рекурсивних шаблонах
У цьому запитанні кілька днів тому було виявлено нескінченну рекурсію під час описування шаблону, коли тип повернення шаблону було вказано 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 Тип заповнювача заповнення може з'являтися разом із декларатором функції у decl-specier-seq, type-specier-seq, id-перетворення-функції або id-типу, що повертається, у будь-якому контексті, де такий декларатор дійсний . Якщо декларатор функцій включає тип зворотного повернення (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)