decltype(auto)的一些用途是什么? [英] What are some uses of decltype(auto)?

查看:317
本文介绍了decltype(auto)的一些用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在c ++ 14中,引入了 decltype(auto) idiom。



通常使用允许 auto 声明使用 decltype 对给定表达式的规则



搜索好的习惯用法的例子我只能想到下面的东西(通过 Scott Meyers ),即函数的返回类型扣除

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

这个新语言功能有用吗?






我的初始示例如下:

  decltype(auto)示例(int const& i){
return i; // return type will beint const&
}


解决方案



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

  auto const&示例(int const& i)
{
return i;
}

但在通用代码完美转发返回类型,而不知道是处理引用还是值。 decltype(auto)赋予您这种能力:

  ,class ... Args> 
decltype(auto)示例(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; }



其他用途


$ b $

b

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



7.1.6.4自动规格[dcl.spec.auto]


1 auto decltype(auto)类型规范指定一个占位符
将被替换的类型稍后,通过从
初始化器中扣除或通过显式指定带尾随返回类型。
auto type-specifier也用于表示lambda是一个
泛型lambda。



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


草稿还包含此变量初始化示例:

  int一世; 
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}; //错误,{1,2}不是一个表达式
auto * x7a =& i; // decltype(x7a)is int *
decltype(auto)* x7d =& i; //错误,声明的类型不是plain decltype(auto)


In c++14 the decltype(auto) idiom is introduced.

Typically its use is to allow auto declarations to use the decltype rules on the given expression.

Searching for examples of "good" usage of the idiom I can only think of things like the following (by Scott Meyers), namely for a function's return type deduction:

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

Are there any other examples where this new language feature is useful?


My initial example was like this :

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

解决方案

Return type forwarding in generic code

For non-generic code, like the initial example you gave, you can manually select to get a reference as a return type:

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

but in generic code you want to be able to perfectly forward a return type without knowing whether you are dealing with a reference or a value. decltype(auto) gives you that ability:

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

Delaying return type deduction in recursive templates

In this Q&A a few days ago, an infinite recursion during template instantiation was encountered when the return type of the template was specified as decltype(iter(Int<i-1>{})) instead of 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) is used here to delay the return type deduction after the dust of template instantiation has settled.

Other uses

You can also use decltype(auto) in other contexts, e.g. the draft Standard N3936 also states

7.1.6.4 auto specifier [dcl.spec.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.

The draft also contains this example of variable initialization:

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)的一些用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆