理解 decltype

理解 decltypeC++11中,的主要用途大概是声明那些返回值型别依赖于形参型别的函数模板。举个例子,如果我们想实现一个函数,其形参中包含一个容器(支持方括号下标语法),该函数会在返回下标操作前进行用户验证,同时要求函数的返回值型别必须与下标操作结果的返回值型别相同。通常含有型别T的容器,其operat

大家好,欢迎来到IT知识分享网。理解

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 的规则



免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/31197.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信