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

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

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

寻找成语“好的”用法的例子,我只能想到下面的事情(通过斯科特•迈耶斯),即函数的返回类型推断:

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

这个新的语言特性还有其他有用的例子吗?

80746 次浏览

在泛型代码中返回类型转发

对于非泛型代码,比如你给出的初始示例,你可以手动选择获取一个引用作为返回类型:

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& < / >强中,当模板的返回类型指定为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 specifier [dcl.spec.auto]

autodecltype(auto)类型说明符指定一个占位符 类型,该类型稍后将被替换,可以从 初始化式或通过显式规范使用拖尾返回类型。 auto类型说明符也用于表示lambda是a 通用的λ。< / p > 占位符类型可以出现,在decl-specifier-seq, type-specifier-seq, convert -function-id,或尾随返回类型,在任何这样的声明器有效的上下文中。如果函数 声明器包括一个尾随返回类型(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)

引用在这里中的内容:

  • decltype(auto)主要用于推断转发函数的返回类型和类似的包装器,在这里您希望类型准确地“跟踪”您正在调用的某个表达式。

  • 例如,给定下面的函数:


   string  lookup1();
string& lookup2();

  • 在c++ 11中,我们可以编写以下包装器函数,记住保留返回类型的引用性:

   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)并不打算成为一个广泛使用的特性。

  • 特别是,虽然可以使用它来声明局部变量,但这样做可能只是一种反模式,因为局部变量的引用性不应该依赖于初始化表达式。

  • 此外,它对您如何编写return语句也很敏感。

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


   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&,这是对局部变量str的引用。

建议你可以看到更多的预期用途。