通用代码中的返回类型转发
对于非通用代码,就像您给出的初始示例一样,您可以手动选择以获取引用作为返回类型:
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
类型SPECI音响儿也用于表示一个lambda是一个通用的λ。
2在此类声明符有效的任何情况下,占位符类型都可以与函数声明符一起出现在decl-specifier-seq,type-specifier-seq,conversion-function-id或tailing-return-type 中。如果函数声明符包括尾随返回类型(8.3.5),则它指定函数的声明返回类型。如果函数的声明的返回类型包含占位符类型,则从函数主体中的return语句(如果有)中推断出函数的返回类型。
草案还包含以下变量初始化示例:
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)