在泛型代码中返回类型转发
对于非泛型代码,比如你给出的初始示例,你可以手动选择获取一个引用作为返回类型:
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 auto specifi儿(dcl规格。auto)
1 The auto and decltype(auto) type-specifiers designate a placeholder
type that will be replaced later, either by deduction from an
initializer or by explicit specification with a trailing-return-type.
The auto type-specifier is also used to signify that a lambda is a
generic lambda.
2 The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq,
conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function
declarator includes a trailing-return-type (8.3.5), that specifies the declared return type of the function.
If the declared return type of the function contains a placeholder type, the return type of the function is
deduced from return statements in the body of the function, if any.
草案还包含了变量初始化的例子:
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)