首页 > 其他分享 >理解 decltype

理解 decltype

时间:2022-10-03 22:55:38浏览次数:53  
标签:decltype 推导 型别 auto C++ 理解 返回值

C++ 11 中,的主要用途大概是声明那些返回值型别依赖于形参型别的函数模板。

        举个例子,如果我们想实现一个函数,其形参中包含一个容器(支持方括号下标语法),该函数会在返回下标操作前进行用户验证,同时要求函数的返回值型别必须与下标操作结果的返回值型别相同。

  通常含有型别 T 的容器,其 operator[] 会返回 T&。例如:std::deque,std::vector 等,当然对于:std::vector<bool>,对应的 operator[] 会返回一个全新的对象,而不是 bool&。

       对于 C++ 11(允许对单表达式的 lambda 式的返回值型别进行推导),可以有下面的写法:(这里使用了返回值型别尾序语法,函数返回值的型别由 decltype(c[i]) 决定,可以使用形参 c,i)

template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i) -> decltype(c[i])   // 返回值型别是根据 decltype(c[i]) 推导出来的
{
    authenticateUser();
    return c[i];
}

  对于 C++ 14(相比于 C++ 11 扩大了适用范围,对一切 lambda 式,一切函数,多表达式都可以进行返回值型别推导),这意味着可以去掉返回值型别尾序语法,而只保留前导 auto,如下:

template<typename Container, typename Index>
auto authAndAccess(Container& c, Index i) -> decltype(c[i])   
{
    authenticateUser();
    return c[i]; // 返回值型别是根据 c[i] 推导出来的
}

std::deque<int> d;
...
aurhAndAccess(d, 5) = 10; // 编译不通过,因为 d[5] 本身型别是 int&,但是 aurhAndAccess 的返回值型别是 int(是一个右值),即给右值赋值 10.


事实上,这种返回值型别推导存在问题,因为这里的 auto 型别推导(本质上是模板型别推导)会忽略初始化表达式的引用性(即 c[i] 的引用性)。

因此在 C++14 中,有另一种写法,如下:
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i)  
{
    authenticateUser();
    return c[i]; 
}  

现在,authAndAccess 的返回值型别与 c[i] 的型别保持一致,因为返回值型别推导使用的是 decltype 型别推导规则。

decltype(auto) 是 C++14中的新用法,其中 auto 指定了要实施推导的型别,而推导过程采用的是 decltype的 型别推导规则。

此外,decltype(auto) 并不局限于函数返回值处使用,在变量声明也可使用,如下:

Widget w;

const Widget& cw = w;

auto myWidget1 = cw;            // auto 型别推导:myWidget1 的型别是 Widget

decltype(auto) myWidget2 = cw   //  decltype(auto) 型别推导:myWidget2 的型别是 const Widget&

 

上述 C++14 的写法还存问题:一个是只能用于左值容器;

为了使函数对右值容器也有作用,可以将函数的形参类型替换为万能应用,当然对万能引用需要使用完美转发来保持型别一致。代码如下:

template<typename Container, typename Index>   // C++14 最终写法
decltype(auto) authAndAccess(Container&& c, Index i)  
{
    authenticateUser();
    return std::forward<Container>(c)[i]; 
} 

template<typename Container, typename Index>   // C++11 最终写法
auto authAndAccess(Container&& c, Index i) -> decltype(std::forward<Container>(c)[i])
{
    authenticateUser();
    return std::forward<Container>(c)[i]; 
} 

 

C++14 支持 decltype(auto),和 auto 一样,它会从其初始化表达式出发来推导型别,但是它的型别推导使用的是 decltype 的规则



标签:decltype,推导,型别,auto,C++,理解,返回值
From: https://www.cnblogs.com/czw-yibao/p/16751509.html

相关文章

  • 深入理解计算机系统大实验
    疑问1:4+6+6的466是什么意思ELF文件的两种格式string2uint函数的状态机模型解析汇编指令的状态机模型关于三重指针的解释符号解析之后的每个符号的结构体smap......
  • flutter系列之:深入理解布局的基础constraints
    目录​​简介​​​​Tight和looseconstraints​​​​理解constraints的原则​​​​总结​​简介我们在flutter中使用layout的时候需要经常对组件进行一些大小的限制,这种......
  • 深入理解Node.js的进程与子进程
    进程:process模块process模块是nodejs提供给开发者用来和当前进程交互的工具,它的提供了很多实用的API。从文档出发,管中窥豹,进一步认识和学习process模块:如何处理命......
  • 01背包&完全背包二维写法的对比,进而理解一维优化后的正逆序
    01背包题解完全背包题解二维写法时两种背包问题核心代码的区别:可以看出,01背包用的是上一层的数据,完全背包用的是当前层的数据所以优化为一维时,01背包需逆序for......
  • 【JS】237-如何理解JavaScript中常用的4种排序算法?
    冒泡排序冒泡排序是我们在编程算法中,算是比较常用的排序算法之一,在学习阶段,也是最需要接触理解的算法,所以我们放在第一个来学习。算法介绍:比较相邻的两个元素,如果前一个比......
  • 用一个例子理解拉格朗日乘数法解决等式约束优化问题
    首先我们来看看一个实例:\[\begin{aligned}&min&f(x,y)&=x^2+y^2\\&s.t.&xy&=3\end{aligned}\]即:在定义域\(xy=3\)内,求\(f(x,y)\)的最小值。两个函数的图像如下:......
  • 用实例并可视化去理解拉格朗日对偶函数的凹性质
    考虑约束最优化问题:\[\begin{aligned}&min&&f(x)\\&s.t.&&c_i(x)\leq0,i=1,2,...,l,\\&&&h_i(x)=0,i=l+1,l+2,...,n\end{aligned}\]拉格朗日化后为:\[\begin{......
  • Prometheus 简单理解
    Prometheus是一款基于时序数据库的开源监控告警系统,非常适合Kubernetes集群的监控。Prometheus内置了一个强大的数据查询语言PromQL。通过PromQL可以实现对监控数据的查......
  • 老猿理解的Python中的垃圾回收机制
    垃圾回收机制(GC)是所有高级语言的标准配置之一。在一定程度上可以优化编程语言的数据处理效率,提高编程软件开发软件的安全性能。Python中的垃圾回收机制主要基于引用计数,......
  • 对于关键路径算法中最迟发生时间取最小值的理解
    问题产生:错误理解:当前事件的最迟发生时间vl(i)的产生跟与之直接关联的后继事件j和中间活动<i,j>有关,如果要使当前事件发生的时间“最晚”,应当取集合{j}中产生的最大......