什么是decltype(自动)的一些用途?

在c ++ 14中引入了decltype(auto)成语。

通常它的用途是允许auto声明在给定的expression式上使用decltype规则

search成语的“好”用法的示例我只能想到像下面这样的东西( Scott Meyers ),即函数的返回types推理

 template<typename ContainerType, typename IndexType> // C++14 decltype(auto) grab(ContainerType&& container, IndexType&& index) { authenticateUser(); return std::forward<ContainerType>(container)[std::forward<IndexType>(index)]; } 

有没有其他的例子,这个新的语言function是有用的?


我最初的例子是这样的:

 decltype(auto) Example(int const& i) { return i; // return type will be "int const&" } 

通用代码中的返回types转发

对于非generics代码,就像您给出的初始示例,您可以手动select以引用作为返回types:

 auto const& Example(int const& i) { return i; } 

但在generics代码中,您希望能够完美地转发返回types,而不必知道您是在处理引用还是值。 decltype(auto)给你这个能力:

 template<class Fun, class... Args> decltype(auto) Example(Fun fun, Args&&... args) { return fun(std::forward<Args>(args)...); } 

延迟recursion模板中的返回types推导

在几天前的Q&A中 ,当模板的返回types被指定为decltype(iter(Int<i-1>{}))而不是decltype(auto)时遇到了模板实例化过程中的无限recursion。

 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)延迟模板实例化尘埃落定之后的返回types扣除

其他用途

您也可以在其他上下文中使用decltype(auto) ,例如,标准N3936草案也有说明

7.1.6.4自动指定器[dcl.spec.auto]

1 autodecltype(auto)types指定符指定一个占位符types,稍后将被replace,可以通过从初始化程序中扣除或通过带有后向返回types的明确说明来replace。 auto type-speci fi er也被用来表示一个lambda是一个通用的lambda。

2占位符types可以在decl-specifier-seq,type-specifier-seq,conversion-function-id或trailing-return-type 中的任何上下文有效的上下文中与函数声明符一起出现 。 如果函数声明符包含一个尾随返回types(8.3.5),它指定了函数声明的返回types。 如果函数声明的返回types包含占位符types,则函数的返回types将从函数主体中的返回语句(如果有)中推导出来。

草案还包含了这个variables初始化的例子:

 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) 

从这里引用的东西:

  • decltype(auto)主要用于推导转发函数的返回types和类似的包装器 ,你希望types能够精确地跟踪你正在调用的expression式。

  • 例如,给定以下function:


  string lookup1(); string& lookup2(); 

  • 在C ++ 11中,我们可以编写下面的包装函数,它们记得保留返回types的引用:

  string look_up_a_string_1() { return lookup1(); } string& look_up_a_string_2() { return lookup2(); } 

  • 在C ++ 14中,我们可以自动化:

  decltype(auto) look_up_a_string_1() { return lookup1(); } decltype(auto) look_up_a_string_2() { return lookup2(); } 

  • 但是, decltype(auto)并不是一个被广泛使用的特性。

  • 特别是,尽pipe它可以用来声明局部variables ,但是这样做可能只是一个反模式,因为局部variables的引用不应该依赖于初始化expression式。

  • 另外,它对你如何编写return语句很敏感。

  • 例如,下面的两个函数具有不同的返回types:


  decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; } decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); } 

  • 第一个返回string ,第二个返回string& ,它是对局部variablesstr的引用。

从提案中可以看到更多的预期用途。