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

专业商铺装修设计seo专业培训费用

专业商铺装修设计,seo专业培训费用,都兰县建设局交通局网站,杭州医疗器械网站制作1.简介 std::decay是C11之后引进的模板编程工具#xff0c;它的主要作用是将给定的类型T转换为它的“衰变”类型。这个“衰变”类型是指去除类型T的所有引用、常量和易变性限定符#xff0c;以及将所有数组和函数转换为对应的指针类型后得到的类型#xff1b;在头文件 …1.简介 std::decay是C11之后引进的模板编程工具它的主要作用是将给定的类型T转换为它的“衰变”类型。这个“衰变”类型是指去除类型T的所有引用、常量和易变性限定符以及将所有数组和函数转换为对应的指针类型后得到的类型在头文件 type_traits 中定义 template class T struct decay; 2.辅助类 2.1.std::remove_reference和std::remove_reference_t 先看实现 template class _Ty struct remove_reference {using type _Ty;using _Const_thru_ref_type const _Ty; };template class _Ty struct remove_reference_Ty { //左值引用using type _Ty;using _Const_thru_ref_type const _Ty; };template class _Ty struct remove_reference_Ty { //右值引用using type _Ty;using _Const_thru_ref_type const _Ty; };template class _Ty using remove_reference_t typename remove_reference_Ty::type; 从上面的代码实现来看它的作用就是擦除类型引用无论是左值引用还是右值引用例如如果_Ty是int或int那么std::remove_reference_t_Ty就是int。示例如下 #include iostream // std::cout #include type_traits // std::is_sametemplateclass T1, class T2 void print_is_same() {std::cout std::is_sameT1, T2() \n; }int main() {std::cout std::boolalpha;print_is_sameint, int(); //输出: trueprint_is_sameint, int (); //输出: falseprint_is_sameint, int (); //输出: falseprint_is_sameint, std::remove_referenceint::type(); //输出: trueprint_is_sameint, std::remove_referenceint ::type(); //输出: trueprint_is_sameint, std::remove_referenceint ::type(); //输出: true } 2.2.std::remove_cv 用于擦除类型的const和volatile限定符返回的是一个去除了const和volatile限定符的类型例如如果T是const int或volatile int那么std::remove_cv_tT就是int。它的实现如下 template class _Ty struct remove_cv { // remove top-level const and volatile qualifiersusing type _Ty;template template class class _Fnusing _Apply _Fn_Ty; // apply cv-qualifiers from the class template argument to _Fn_Ty };template class _Ty struct remove_cvconst _Ty { //擦除constusing type _Ty;template template class class _Fnusing _Apply const _Fn_Ty; };template class _Ty struct remove_cvvolatile _Ty { //擦除volatile using type _Ty;template template class class _Fnusing _Apply volatile _Fn_Ty; };template class _Ty struct remove_cvconst volatile _Ty { //擦除const volatileusing type _Ty;template template class class _Fnusing _Apply const volatile _Fn_Ty; };template class _Ty using remove_cv_t typename remove_cv_Ty::type; 示例如下 #include iostream #include type_traitsint main() {typedef std::remove_cvconst int::type type1;typedef std::remove_cvvolatile int::type type2;typedef std::remove_cvconst volatile int::type type3;typedef std::remove_cvconst volatile int*::type type4;typedef std::remove_cvint * const volatile::type type5;std::cout test1 (std::is_sameint, type1::value? passed : failed) \n;std::cout test2 (std::is_sameint, type2::value? passed : failed) \n;std::cout test3 (std::is_sameint, type3::value? passed : failed) \n;std::cout test4 (std::is_sameconst volatile int*, type4::value? passed : failed) \n;std::cout test5 (std::is_sameint*, type5::value? passed : failed) \n; } 输出 test1 passed test2 passed test3 passed test4 passed test5 passed 2.3.std::is_array template class T struct is_array; 主要是判断 T 是否为数组类型如果 T 为数组类型那么成员常量 value 等于 true。对于其它类型value 等于 false,  它的实现如下 template class _INLINE_VAR constexpr bool is_array_v false; // determine whether type argument is an arraytemplate class _Ty, size_t _Nx _INLINE_VAR constexpr bool is_array_v_Ty[_Nx] true;template class _Ty _INLINE_VAR constexpr bool is_array_v_Ty[] true;template class _Ty struct is_array : bool_constantis_array_v_Ty {}; 从源码很清晰的看到当输入为数组类型的时候特例化返回true。示例如下 #include array #include iostream #include type_traitsclass A {};int main() {std::cout std::boolalpha;std::cout std::is_arrayA::value \n; //输出: falsestd::cout std::is_arrayA[]::value \n; //输出: truestd::cout std::is_arrayA[3]::value \n; //输出: truestd::cout std::is_arrayfloat::value \n; //输出: falsestd::cout std::is_arrayint::value \n; //输出: falsestd::cout std::is_arrayint[]::value \n; //输出: truestd::cout std::is_arrayint[3]::value \n; //输出: true std::cout std::is_arraystd::arrayint, 3::value \n; //输出: false } 2.4.std::is_function std::is_function(C11)用于检查类型是否为函数注意此处函数类型不包括std::function, lambda, 有重载operator()的类它的实现如下 template class _Ty _INLINE_VAR constexpr bool is_function_v // only function types and reference types cant be const qualified!is_const_vconst _Ty !is_reference_v_Ty;template class _Ty struct is_function : bool_constantis_function_v_Ty {}; 示例如下 #include iostream #include type_traitsstruct A {int fun() const; };templatetypename struct PM_traits {};templateclass T, class U struct PM_traitsU T::* {using member_type U; };int f();int main() {std::cout std::boolalpha;std::cout std::is_functionA::value \n; //输出 : falsestd::cout std::is_functionint(int)::value \n; //输出 : truestd::cout std::is_functiondecltype(f)::value \n; //输出 : truestd::cout std::is_functionint::value \n; //输出 : falseusing T PM_traitsdecltype(A::fun)::member_type; // T 为 int() conststd::cout std::is_functionT::value \n; //输出 : true } 2.5.std::remove_extent 它的作用是给数组移除一个维度注意若 T 是多维数组则只移除第一维。它的实现如下 template class _Ty struct remove_extent { // remove array extentusing type _Ty; };template class _Ty, size_t _Ix struct remove_extent_Ty[_Ix] {using type _Ty; };template class _Ty struct remove_extent_Ty[] {using type _Ty; };template class _Ty using remove_extent_t typename remove_extent_Ty::type; 多维数组如果要全部移除维度则要用std::remove_all_extents, std::remove_all_extents实现如下 template class _Ty struct remove_all_extents { // remove all array extentsusing type _Ty; };template class _Ty, size_t _Ix struct remove_all_extents_Ty[_Ix] {using type typename remove_all_extents_Ty::type; };template class _Ty struct remove_all_extents_Ty[] {using type typename remove_all_extents_Ty::type; };template class _Ty using remove_all_extents_t typename remove_all_extents_Ty::type; 这里巧妙的借助元编程中模板类的偏特化和递归继承属性: 定义的remove_all_extents偏特化版本继承自身通过不断地递归继承直到remove_all_extentsT类型与T类型完全相同时调用普通版本完成递归调用所有的递归调用过程均在编译期完成从这个例子中可以看出模板元编程的真正魅力所在。 示例如下 #include iostream #include iterator #include algorithm #include type_traitstemplateclass A typename std::enable_if std::rankA::value 1 ::type print_1d(const A a) {copy(a, astd::extentA::value,std::ostream_iteratortypename std::remove_extentA::type(std::cout, ));std::cout \n; }int main() {int a[][3] {{1,2,3},{4,5,6}}; // print_1d(a); // 编译时错误print_1d(a[1]); //输出 4 5 6 } 2.6.std::add_pointer std::add_pointer模板可以把一个类型转换为指针类型它的实现 template class _Ty, class void struct _Add_pointer { // add pointer (pointer type cannot be formed)using type _Ty; };template class _Ty struct _Add_pointer_Ty, void_tremove_reference_t_Ty* { // (pointer type can be formed)using type remove_reference_t_Ty*; };template class _Ty struct add_pointer {using type typename _Add_pointer_Ty::type; };template class _Ty using add_pointer_t typename _Add_pointer_Ty::type; 示例如下 #include iostream #include type_traitsusing namespace std;int main() {typedef add_pointerint::type ptr; // ptr 是 int* 类型cout is_sameint*, ptr::value endl; // 输出 truereturn 0; } 在上面例子中我们使用add_pointer模板将类型int转换为指针类型int*并声明了别名ptr。可以看到使用add_pointer模板可以快速实现类型转换。 2.7.std::conditional std::conditional模板可以根据条件进行类型选择, 实现如下 template bool _Test, class _Ty1, class _Ty2 struct conditional { // Choose _Ty1 if _Test is true, and _Ty2 otherwiseusing type _Ty1; };template class _Ty1, class _Ty2 struct conditionalfalse, _Ty1, _Ty2 {using type _Ty2; };template bool _Test, class _Ty1, class _Ty2 using conditional_t typename conditional_Test, _Ty1, _Ty2::type; 示例如下 #include iostream #include type_traits #include typeinfoint main() {typedef std::conditionaltrue, int, double::type a;typedef std::conditionalfalse, int, double::type b;typedef std::conditionalsizeof(int) sizeof(double), int, double::type c;std::cout typeid(a).name() \n;std::cout typeid(b).name() \n;std::cout typeid(c).name() \n; } 3.可能实现 介绍完上面的基础知识后根据std::decay的功能猜测大致可能的实现如下 templateclass T struct decay { private:typedef typename std::remove_referenceT::type U; public:typedef typename std::conditional std::is_arrayU::value,typename std::remove_extentU::type*,typename std::conditional std::is_functionU::value,typename std::add_pointerU::type,typename std::remove_cvU::type::type::type type; }; 分析步骤 1)  擦除引用类型。例如 int和int 返回 int 2如果是数组返回的就是数组存放的数据类型。例如int[10] 返回 int 3如果是函数返回的就是函数指针。例如int (int) 返回 int (*)(int) 4)  除2和3之外的其它类型则擦除const、volatile 或 const volatile。 4.源码分析 根据第3部分讲解的实现流程在VS2019上是怎么实现上面的功能呢不隐藏直接上源码 template bool struct _Select { // Select between aliases that extract either their first or second parametertemplate class _Ty1, classusing _Apply _Ty1; };template struct _Selectfalse {template class, class _Ty2using _Apply _Ty2; };template class _Ty struct decay { // determines decayed version of _Tyusing _Ty1 remove_reference_t_Ty;using _Ty2 typename _Selectis_function_v_Ty1::template _Applyadd_pointer_Ty1, remove_cv_Ty1;using type typename _Selectis_array_v_Ty1::template _Applyadd_pointerremove_extent_t_Ty1, _Ty2::type; };template class _Ty using decay_t typename decay_Ty::type;从上面的代码可以看出把std::conditional替换成了_Select而_Select的功能和std::conditional是一模一样的代码的逻辑和第3部分分析的也是一模一样的在这里就不再过多赘述了。 5.使用 1在之前我的从C容器中获取存储数据的类型-CSDN博客中从容器中获取所存储的数据类型就用到了std::decay在函数func获取跟容器中一样数据类型如下代码 #include iostream #include boost/type_index.hpptemplate typename Container void func(Container t, const char* pMessage) {using TYPE std::decaydecltype(*t.begin());std::cout pMessage boost::typeindex::type_id_with_cvrdecltype(TYPE)().pretty_name() std::endl; } 调用函数decltype(*t.begin()出来还是引用类型通过std::decay退变成真正的原始类型Container::value_type。 2示例如下 #include iostream #include type_traitstemplate typename T, typename U struct decay_equiv : std::is_sametypename std::decayT::type, U::type {};int main() {std::cout std::boolalpha decay_equivint, int::value \n /*1*/ decay_equivint, int::value \n /*2*/ decay_equivint, int::value \n /*3*/ decay_equivconst int, int::value \n /*4*/ decay_equivint[2], int*::value \n /*5*/ decay_equivint(int), int(*)(int)::value \n; /*6*/ } 上面的代码第1部分是传入int就是普通类型传出也是int 上面的代码第2部分是传入int通过std::decay擦除左值引用传出int 上面的代码第3部分是传入int通过std::decay擦除右值引用传出int 上面的代码第4部分是传入const int通过std::decay擦除左值引用去掉const传出int 上面的代码第5部分是传入一维数组int[2]通过std::decay移除一个维度退化传出int* 上面的代码第6部分是传入函数int(int)通过std::decay添加指针传出指向传入函数的指针int(*(int)。 6.注意事项 1、虽然std::decay可以处理许多类型的转换但是它不能处理所有的类型。例如std::decay不能处理类类型枚举类型和联合类型。 2、std::decay只能用于模板参数。如果我们尝试在非模板参数上使用std::decay编译器将会报错。 3、std::decay不能用于消除指针类型。如果我们尝试在指针类型上使用std::decaystd::decay将不会有任何效果。 7.总结 std::decay是我们平时模版编程中使用的比较多的在实际模板编程或者模板元编程中非常有用在type_traits源代码里处处可见实际工作中也会经常用到上面的介绍只是抛砖引玉要想真正掌握它只有的不停地使用在使用过程中遇到问题解决问题才能真正理解它的原理灵活使用。
http://www.pierceye.com/news/504123/

相关文章:

  • 二级目录网站怎么做小程序开发成都公司
  • 网站标题名字和备案名字网站开发 质量管理
  • 网站与系统开发吉安网站建设收费
  • 湖北襄阳网站建设wordpress电商ar
  • 微做网站环保行业网站建设
  • 昭通做网站公司北京手机网站制作多少钱
  • 昆明企业建网站多少钱如何弄微信小程序
  • wordpress清理网站缓存做的比较简约的网站
  • 青岛高端网站制作中铁建设集团门户密码
  • 公司专业做网站做网站域名起什么作用
  • 推广型网站建设机构如何创建wordpress
  • 做网站交互demo工具在线设计自己的签名免费
  • 做百度推广会送网站吗网站建设和邮箱的关联
  • 假网站如何做济南天桥区网站建设
  • 顺企网我做网站余姚网站建设在哪里
  • 做网站logo用啥软件做电子书网站
  • 企业网站推广的策略有哪些php怎么建立站点
  • 找网站设计公司 看那些wordpress居中
  • 无锡网站营销公司哪家好全屏网页设计尺寸
  • 做第一个网站什么类型网站搜索引擎优化案例
  • 网站代码生成网站网站开发专业 工作意愿
  • ps做网站效果图尺寸如何重庆网站建设选夹夹虫
  • 上鼎工程建设有限公司网站最简单的手机网站制作
  • 网站维护企业网站的后缀名
  • 建设网站需要哪些认证做公众号的网站模板下载吗
  • 搜狗提交网站入口Wordpress登录后顶部的黑
  • 计算机网络技术就业方向及前景西安seo网站排名优化公司
  • 手机网站要求软文推广图片
  • 网站在哪里建立用h5开发的网站模板
  • 深圳建英文网站小学生作文网