decltype(auto) 有哪些用途?

问题描述 投票:0回答:2

在 c++14 中引入了

decltype(auto)
习惯用法。

通常它的用途是允许

auto
声明在给定表达式
上使用
decltype
规则。

搜索该习语的“良好”用法的示例,我只能想到以下内容(由Scott Meyers),即函数的返回类型推导

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

这个新语言功能还有其他有用的例子吗?

c++ c++14 decltype return-type-deduction decltype-auto
2个回答
241
投票

通用代码中的返回类型转发

对于非通用代码,就像您给出的初始示例一样,您可以手动选择获取引用作为返回类型:

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
类型说明符也用于表示 lambda 是一个 通用 lambda。

2 占位符类型可以与函数声明符一起出现在decl-specifier-seq、type-specifier-seq、 conversion-function-id 或 Trailing-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)
    

48
投票
引用

这里的内容

  • 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
    的引用。

提案您可以看到更多预期用途。

© www.soinside.com 2019 - 2024. All rights reserved.