当前位置: 首页 > wzjs >正文

国内坚持做正品的网站openwrt 做视频网站

国内坚持做正品的网站,openwrt 做视频网站,wordpress前台多语言,哪个网站做的ppt模板好文章目录 理解模板类型推导理解auto类型推导理解decltype学会查看类型推导结果 理解模板类型推导 c的auto特性是建立在模板类型推到的基础上。坏消息是当模板类型推导规则应用于auto环境时,有时不如应用于template时那么直观。我们可能很自然的期望T和传递进函数的…

文章目录

  • 理解模板类型推导
  • 理解auto类型推导
  • 理解decltype
  • 学会查看类型推导结果

理解模板类型推导

c++的auto特性是建立在模板类型推到的基础上。坏消息是当模板类型推导规则应用于auto环境时,有时不如应用于template时那么直观。我们可能很自然的期望T和传递进函数的实参是相同的类型,也就是,Texpr的类型。但有时情况并非总是如此,T的类型推导不仅取决于expr的类型,也取决于ParamType的类型。这里有三种情况:

template<typename T>
void f(ParamType param)

情景一:ParamType是一个指针或引用,但不是通用引用

  1. 如果expr类型是一个引用,会忽略引用部分【因为引用部分独立于T】
  2. 然后expr的类型与ParamType进行模式匹配来决定T

情景二:ParamType是一个通用引用(T&&)

  1. 如果expr是左值,T和paramType都会被推到为左值引用。第一,这是模板类型推导中唯一一种T被推导为引用的情况。
  2. 如果expr是右值,就使用正常的(也就是情景一)推导规则(忽略引用后于ParamType进行模式匹配来决定T)

情景三:ParamType既不是指针也不是引用

void f(T param);

  1. 和之前一样,如果expr的类型是一个引用,忽略这个引用部分
  2. 如果忽略expr的引用性(reference-ness)之后,expr是一个const,那就再忽略const。如果它是volatile,也忽略volatilevolatile对象不常见,它通常用于驱动程序的开发中。关于volatile的细节请参见40)

忽略引用行在指向常量的常量指针情况下只会忽略底层const,这一特性只会对形参本身有效,因此指针的常量特定会被忽略,但是指针所指对象的常量特性会被保留。

在类型推导中,这个指针指向的数据的常量性constness将会被保留,但是当拷贝ptr来创造一个新指针param时,ptr自身的常量性constness将会被忽略。

特殊情况:数组实参(函数类似)

在大多数情况下数组会被退化为指针。如果我们ParamType就是T,那么传递数组实参和传递指针形参情况类似,推断的结果是一个指针。但是如果声明为传递引用形参的模板,T被推到为真正的数组!

template<typename T>
void f(T& param);       
f(name);//name是一个数组指向const char[13],T也是一个数组,且ParamType为const char(&)[13]

有趣的是,可声明指向数组的引用的能力,使得我们可以创建一个模板函数来推导出数组的大小:

//在编译期间返回一个数组大小的常量值(//数组形参没有名字,
//因为我们只关心数组的大小)
template<typename T, std::size_t N>                     //关于
constexpr std::size_t arraySize(T (&)[N]) noexcept      //constexpr
{                                                       //和noexceptreturn N;                                           //的信息
}                                                       //请看下面

总结

  • 在模板类型推导时,有引用的实参会被视为无引用,他们的引用会被忽略
  • 对于通用引用的推导,左值实参会被特殊对待
  • 对于传值类型推导,const和/或volatile实参会被认为是non-const的和non-volatile
  • 在模板类型推导时,数组名或者函数名实参会退化为指针,除非它们被用于初始化引用

理解auto类型推导

当一个变量使用auto进行声明时,auto扮演了模板中T的角色,变量的类型说明符扮演了ParamType的角色。废话少说,这里便是更直观的代码描述,考虑这个例子:


template<typename T>            //概念化的模板用来推导x的类型
void func_for_x(T param);
auto x=27;
func_for_x(27);                 //概念化调用://param的推导类型是x的类型template<typename T>            //概念化的模板用来推导cx的类型
void func_for_cx(const T param);
const auto cs=x;
func_for_cx(x);                 //概念化调用://param的推导类型是cx的类型template<typename T>            //概念化的模板用来推导rx的类型
void func_for_rx(const T & param);
const auto& rx=x
func_for_rx(x);                 //概念化调用://param的推导类型是rx的类型

不同于模板类型推导的特殊情况

这就造成了auto类型推导不同于模板类型推导的特殊情况。当用auto声明的变量使用花括号进行初始化,auto类型推导推出的类型则为std::initializer_list。如果这样的一个类型不能被成功推导(比如花括号里面包含的是不同类型的变量),编译器会拒绝这样的代码:

auto x1 = 27;                   //类型是int,值是27
auto x2(27);                    //同上
auto x3 = { 27 };               //类型是std::initializer_list<int>,//值是{ 27 }
auto x4{ 27 };                  //同上auto x5 = { 1, 2, 3.0 };        //错误!无法推导std::initializer_list<T>中的T

对于模板,无法推导花括号为std::initializer_list

template<typename T>
void f(std::initializer_list<T> initList);f({ 11, 23, 9 });               //T被推导为int,initList的类型为//std::initializer_list<int>

新标准:

==在c++14允许auto用于函数返回值并会被推导。==c++14也允许lambda函数在形参声明中使用auto,但是在这些情况下,auto实际使用模板类型推导的那一套规则在工作,而不是auto类型推导。所以下面这样的代码不会通过编译。

auto createInitList(){return {1,2,3};
}
std::vector<int> v;auto resetV = [&v](const auto& newValue){ v = newValue; };        //C++14resetV({ 1, 2, 3 });            //错误!不能推导{ 1, 2, 3 }的类型

理解decltype

我们将从一个简单的情况开始,没有任何令人惊讶的情况。相比模板类型推导和auto类型推导,decltype只是简单的返回名字或者表达式的类型(不会忽略const和引用)。decltype作用与返回左值的表达式得到的是一个引用。(我们可以为返回左值的表达式赋值)。例如decltype中表达式的内容是一个解引用(*p),返回的并不是指针所指向的对象本身,而是一个引用。

在C++11中,decltype最主要的用途就是用于声明函数模板,而这个函数返回类型依赖于形参类型。函数名称前面的auto不会做任何的类型推导工作。相反的,他只是暗示使用了C++11的尾置返回类型语法,即在函数形参列表后面使用一个”->“符号指出函数的返回类型,尾置返回类型的好处是我们可以在函数返回类型中使用函数形参相关的信息。

template<typename Container, typename Index>    //可以工作,
auto authAndAccess(Container& c, Index i)       //但是需要改良->decltype(c[i])
{authenticateUser();return c[i];
}

C++11允许自动推导单一语句的lambda表达式的返回类型, C++14扩展到允许自动推导所有的lambda表达式和函数,甚至它们内含多条语句。对于authAndAccess来说这意味着在C++14标准下我们可以忽略尾置返回类型,只留下一个auto。使用这种声明形式,auto标示这里会发生类型推导。更准确的说,编译器将会从函数实现中推导出函数的返回类型。

然而这么做会出现一个问题,大多数T类型的容器会返回一个T&,但是模板类型推导期期间,表达式的引用性会被忽略。要想让authAndAccess像我们期待的那样工作,我们需要使用decltype类型推导来推导它的返回值,即指定authAndAccess应该返回一个和c[i]表达式类型一样的类型。

c++14中可以使用decltype(auto)说明符使得这成为可能。实际上我们可以这样解释它的意义:auto说明符表示这个类型将会被推导,decltype说明decltype的规则将会被用到这个推导过程中。因此我们可以这样写authAndAccess

decltype(auto)的使用不仅仅局限于函数返回类型,当你想对初始化表达式使用decltype推导的规则,你也可以使用:

template<typename Container, typename Index>    //C++14版本,
decltype(auto)                                  //可以工作,
authAndAccess(Container& c, Index i)            //但是还需要
{                                               //改良authenticateUser();return c[i];
}
decltype(auto) muWidget2 = cw;

上述authAndAccess函数实际上还存在一些漏洞。为了使函数支持左值引用和右值引用==(这种情况很少,但向authAndAccess传递一个临时变量也并不是没有意义,有时候用户可能只是想简单的获得临时容器中的一个元素的拷贝,比如这样)==,我们需要将声明改为通用引用(也可以重载函数)。

注意这里我们也并不知道index的类型,但我们并没有声明为引用的形式。因为就容器索引来说,我们遵照标准模板库对于索引的处理是有理由的(比如std::stringstd::vectorstd::dequeoperator[]),所以我们坚持传值调用。

最后我们用std::forward来实现通用引用(22)

template<typename Container, typename Index>    //最终的C++14版本
decltype(auto)
authAndAccess(Container&& c, Index i)
{authenticateUser();return std::forward<Container>(c)[i];//使用std::forward保证实参c和形参c的引用类型一致(都是左值引用或右值引用)
}
//对于c++11需要用尾置返回值
//->decltype(std::forward<Contrainer>(c)[i])

特殊情况

decltype应用于变量名会产生该变量名的声明类型。然而,对于比单纯的变量名更复杂的左值表达式,decltype可以确保报告的类型始终是左值引用。也就是说,如果一个不是单纯变量名的左值表达式的类型是T,那么decltype会把这个表达式的类型报告为T&

我们回到最开始说的*p的情况,p是一个单纯变量名,如果decltype§返回的是p的声明类型,然而*p是返回左值的复杂表达式了,因此decltype返回的是左值引用,类型是表达式的类型。

总结

decltype(单独使用或者与auto一起用)可能会偶尔产生一些令人惊讶的结果,但那毕竟是少数情况。通常,decltype都会产生你想要的结果,尤其是当你对一个变量使用decltype时,因为在这种情况下,decltype只是做一件本分之事:它产出变量的声明类型。

  • decltype总是不加修改的产生变量或者表达式的类型。
  • 对于T类型的不是单纯的变量名的左值表达式,decltype总是产出T的引用即T&
  • C++14支持decltype(auto),就像auto一样,推导出类型,但是它使用decltype的规则进行推导。

学会查看类型推导结果

我们探究三种方案:在你编辑代码的时候获得类型推导的结果,在编译期间获得结果,在运行时获得结果。

IDE编辑器

在IDE中的代码编辑器通常可以显示程序代码中变量,函数,参数的类型,你只需要简单的把鼠标移到它们的上面,举个例子,有这样的代码中:

运行时输出

std::cout << typeid(x).name() << '\n';  //显示x和y的类型
std::cout << typeid(y).name() << '\n';

调用std::type_info::name不保证返回任何有意义的东西,但是库的实现者尝试尽量使它们返回的结果有用。实现者们对于“有用”有不同的理解。举个例子,GNU和Clang环境下x的类型会显示为”i“,y会显示为”PKi“,这样的输出你必须要问问编译器实现者们才能知道他们的意义:”i“表示”int“,”PK“表示”pointer to konst const“(指向常量的指针)。(这些编译器都提供一个工具c++filt,解释这些“混乱的”类型)Microsoft的编译器输出得更直白一些:对于x输出”int“对于y输出”int const *

std::type_info::name规范批准像传值形参一样来对待这些类型。正如item1中提到的,如果传递的是一个引用,那么引用部分(reference-ness)将被忽略,如果忽略后还具有const或者volatile,那么常量性constness或者易变性volatileness也会被忽略。

依赖于库

std::type_info::name和IDE失效的地方,Boost TypeIndex库(通常写作Boost.TypeIndex)被设计成可以正常运作。这个库不是标准C++的一部分,也不是IDE或者TD这样的模板。Boost库(可在boost.com获得)是跨平台,开源,有良好的开源协议的库,这意味着使用Boost和STL一样具有高度可移植性。

这里是如何使用Boost.TypeIndex得到f的类型的代码

#include <boost/type_index.hpp>template<typename T>
void f(const T& param)
{using std::cout;using boost::typeindex::type_id_with_cvr;//显示Tcout << "T =     "<< type_id_with_cvr<T>().pretty_name()<< '\n';//显示param类型cout << "param = "<< type_id_with_cvr<decltype(param)>().pretty_name()<< '\n';
}std::vetor<Widget> createVec();         //工厂函数
const auto vw = createVec();            //使用工厂函数返回值初始化vw
if (!vw.empty()){f(&vw[0]);                          //调用f}
//假设vw是一个const类型,我们传递的是其中一个元素的地址(该元素也是const),因此T被推断为const(底层const保留)和*,而param 被推断为const * const&,顶层const在形参列表中写明,&在形参列表中写明。T =     Widget const *
param = Widget const * const&

文章转载自:

http://2sgN4HfE.wLjzr.cn
http://S4lK5Zsm.wLjzr.cn
http://7HpytNpu.wLjzr.cn
http://bAj4H4vd.wLjzr.cn
http://I7BK7CzF.wLjzr.cn
http://1FKesxnC.wLjzr.cn
http://NLSWvq7Z.wLjzr.cn
http://lmUBsGyU.wLjzr.cn
http://Ni4e95oK.wLjzr.cn
http://YGPkKmnH.wLjzr.cn
http://l5DasTrp.wLjzr.cn
http://5EWHsSkk.wLjzr.cn
http://iGlMUnBF.wLjzr.cn
http://vF0yzEdT.wLjzr.cn
http://18Zr8AmS.wLjzr.cn
http://eUQxBdGe.wLjzr.cn
http://ygIuPmxu.wLjzr.cn
http://kQa2Z8EY.wLjzr.cn
http://X9UJaH92.wLjzr.cn
http://oES0qBU0.wLjzr.cn
http://XxLXBeVc.wLjzr.cn
http://xyCFcUQW.wLjzr.cn
http://4kG5WuPJ.wLjzr.cn
http://FigsFfRC.wLjzr.cn
http://M78Efu7C.wLjzr.cn
http://S1krImTY.wLjzr.cn
http://n85rcHVV.wLjzr.cn
http://IdO5Eedk.wLjzr.cn
http://fQ8wN9vK.wLjzr.cn
http://uAYjeb9I.wLjzr.cn
http://www.dtcms.com/wzjs/769496.html

相关文章:

  • 甘肃建设体网站百度智能小程序
  • 增城手机网站建设做网站要准备哪些
  • 自建国际网站做电商程序小程序开发
  • 做贸易做个外贸网站有必要吗网站备案用的幕布可以淘宝做吗
  • 二手网站建设论文答辩网站建设的目标定位
  • 网站访问速度跟服务器cpu和内存和带宽哪个重要网站建设怎么接单
  • 成都网站设计制作工作室西安建设厅网站首页
  • 站长工具whois查询网站设计设计方案
  • html5 开发网站大理企业网站建设
  • 阜阳市建设工程质量检测站网站如何查网站备案号
  • 学网站开发培训学校南宁手机模板建站
  • .net网站开发实训泰安网站建设个人工作室
  • 网站建设影音先锋网址网站开发图书管理系统
  • 深圳企业建站程序做网站 提要求
  • 网站黑链怎么做的衡水做wap网站建设
  • 厦门h5网站建设重庆建设汽车系统股份有限公司
  • 农业技术推广网站北京市住房及城乡建设网站
  • 网站建设的所有权百度一下百度搜索百度
  • 如何建立简单网站微信网站特征
  • 商场网站开发百度网盘怎么提取别人资源
  • 设计感强的网站wordpress卸载
  • 如何在网上做网站齐诺网站建设东莞网站建设做网站
  • 静态网站优化网络设计目标
  • 网站开发需要资质吗如何防止网站被采集
  • 常熟有做网站的网络公司吗建设部网站白蚁文件
  • 网站建设】vs2015 做网站
  • 网站开发数据库郑州前端培训机构
  • 制作网站需要wordpress个人智慧团建网站
  • 网站竞价词怎么做网络营销实务技能训练题答案
  • 做网站的公司搞什么活动h5的制作步骤