小编典典

decltype(auto) 有哪些用途?

all

在 c++14decltype(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)];
}

是否有任何其他示例表明此新语言功能很有用?


阅读 63

收藏
2022-07-18

共1个答案

小编典典

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

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

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]

1autodecltype(auto)类型说明符指定稍后将被替换的占位符类型,或者通过从初始化程序中推导,或者通过带有尾随返回类型的显式说明符。type-
speci铿乪autor 也用于表示 lambda 是通用 lambda。

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

草案还包含这个变量初始化的例子:

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)
2022-07-18