c++新经典模板与泛型编程:const修饰符的移除与增加

const修饰符的移除

让你来写移除const修饰符,你会怎么样来写?
😂😂trait类模板,如下


#include <iostream>

// 泛化版本
template<typename T>
struct RemoveConst
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveConst<const T>
{
	using type = T;
};

// 根据需要,可能还要增加其他特化版本
template<typename T>
using RemoveConst_t = typename RemoveConst<T>::type;


int main()
{
	// nca 是int类型
	// c++标准库中的std::remove_const也比较类似
	RemoveConst_t<const int> nca = 15;

	// 可以给nca重新赋值
	nca = 18;
	
	return 0;
}

退化技术

  1. 某些类型一旦传递给函数模板(通过函数模板来推断相关的类型),那么推断出来的类型就会产生退化。所谓退化(decay),就是把类型中的一些修饰符丢弃了。例如,const int中的const丢弃后,就变成int类型,那么对于const int类型,int类型就是一种退化的表现。
  2. c++标准库中有一个类模板std::decay,这个类模板的作用就是把一个类型退化掉(就是把类型中的一些修饰符丢掉)。
	std::decay<const int&>::type nb = 28;
	// nb的类型为int类型
	std::cout << "nb的类型为:" << typeid(decltype(nb)).name() << std::endl;

如何实现一个类似std::decay功能的trait类模板呢?

// b.cpp
int g_array[10];

// main.cpp
#include <iostream>

// 泛化版本
template<typename T>
struct RemoveReference
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveReference<T&>
{
	using type = T;
};
template<typename T>
struct RemoveReference<T&&>  // 这个特化能适应 const T&&应该是伴随我一生,难以理解的噩梦了
{
	using type = T;
};

// 泛化版本
template<typename T>
struct RemoveConst
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveConst<const T>
{
	using type = T;
};

// 根据需要,可能还要增加其他特化版本
template<typename T>
using RemoveConst_t = typename RemoveConst<T>::type;

template<typename T>
struct RemoveCR : RemoveConst<typename RemoveReference<T>::type>
{ // 把const和引用修饰符去掉
};

template<typename T>
using RemoveCR_t = typename RemoveCR<T>::type;

// Decay的trait类模板
// 泛化版本
template<typename T>
struct Decay : RemoveCR<T>
{
};


// 特化版本,这个特化版本没有继承任何父类
// 有边界数组转换成指针
template<typename T,std::size_t size>
struct Decay<T[size]>
{
	using type = T*;
};

// 无边界数组转换成指针
template<typename T>
struct Decay<T[]>
{
	using type = T*;
};

extern int g_array[];


int main()
{
	RemoveCR_t<const int&&> rcrobj = 15; // rcrobj为int类型,只能叹为观止,惊叹rcrobj鬼斧神工地成了int类型

	int arr[2] = { 1,2 };
	Decay<decltype(arr)>::type my_array;
	std::cout << "my_array的类型为: " << typeid(decltype(my_array)).name() << std::endl;

	Decay<decltype(g_array)>::type my_array_2;
	std::cout << "my_array_2的类型为:" << typeid(decltype(my_array_2)).name() << std::endl;


	return 0;
}

在这里插入图片描述

  1. 上述函数代表类型:void()
  2. 可以使用函数指针指向某种函数类型,如果指向void(),函数指针应该是void(*)()
  3. 如果不为函数名退化为函数指针写一个Decay的特化版本,那么,传入testFunc2这个函数类型,
    得到的返回类型依旧是void(),换句话说传入什么类型,就返回什么类型

#include <iostream>

// 泛化版本
template<typename T>
struct RemoveReference
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveReference<T&>
{
	using type = T;
};
template<typename T>
struct RemoveReference<T&&>  // 这个特化能适应 const T&&应该是伴随我一生,难以理解的噩梦了
{
	using type = T;
};

// 泛化版本
template<typename T>
struct RemoveConst
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveConst<const T>
{
	using type = T;
};

// 根据需要,可能还要增加其他特化版本
template<typename T>
using RemoveConst_t = typename RemoveConst<T>::type;

template<typename T>
struct RemoveCR : RemoveConst<typename RemoveReference<T>::type>
{ // 把const和引用修饰符去掉
};

template<typename T>
using RemoveCR_t = typename RemoveCR<T>::type;

// Decay的trait类模板
// 泛化版本
template<typename T>
struct Decay : RemoveCR<T>
{
};


// 特化版本,这个特化版本没有继承任何父类
// 有边界数组转换成指针
template<typename T,std::size_t size>
struct Decay<T[size]>
{
	using type = T*;
};

// 无边界数组转换成指针
template<typename T>
struct Decay<T[]>
{
	using type = T*;
};

extern int g_array[];

// 简单的函数
void testFunc2()
{
	std::cout << "testFunc2()执行了" << std::endl;
}

void rfunc()
{
	std::cout << "rfunc执行了" << std::endl;
}



int main()
{
	RemoveCR_t<const int&&> rcrobj = 15; // rcrobj为int类型,只能叹为观止,惊叹rcrobj鬼斧神工地成了int类型

	int arr[2] = { 1,2 };
	Decay<decltype(arr)>::type my_array;
	std::cout << "my_array的类型为: " << typeid(decltype(my_array)).name() << std::endl;

	Decay<decltype(g_array)>::type my_array_2;
	std::cout << "my_array_2的类型为:" << typeid(decltype(my_array_2)).name() << std::endl;

	// 2
	Decay<decltype(testFunc2)>::type rfunc;
	std::cout << "rfunc类型为:" << typeid(decltype(rfunc)).name() << std::endl;
	rfunc();


	return 0;
}

在这里插入图片描述

现在容易理解写一个Decay特化版本把函数名(退化成)函数指针这件事了
因为函数可能有任何的返回类型以及任何数量和类型的参数,所以这个Decay的特化版本比较特殊
需要可变参模板来实现


#include <iostream>

// 泛化版本
template<typename T>
struct RemoveReference
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveReference<T&>
{
	using type = T;
};
template<typename T>
struct RemoveReference<T&&>  // 这个特化能适应 const T&&应该是伴随我一生,难以理解的噩梦了
{
	using type = T;
};

// 泛化版本
template<typename T>
struct RemoveConst
{
	using type = T;
};

// 特化版本
template<typename T>
struct RemoveConst<const T>
{
	using type = T;
};

// 根据需要,可能还要增加其他特化版本
template<typename T>
using RemoveConst_t = typename RemoveConst<T>::type;

template<typename T>
struct RemoveCR : RemoveConst<typename RemoveReference<T>::type>
{ // 把const和引用修饰符去掉
};

template<typename T>
using RemoveCR_t = typename RemoveCR<T>::type;

// Decay的trait类模板
// 泛化版本
template<typename T>
struct Decay : RemoveCR<T>
{
};


// 特化版本,这个特化版本没有继承任何父类
// 有边界数组转换成指针
template<typename T,std::size_t size>
struct Decay<T[size]>
{
	using type = T*;
};

// 无边界数组转换成指针
template<typename T>
struct Decay<T[]>
{
	using type = T*;
};

extern int g_array[];

// 简单的函数
void testFunc2()
{
	std::cout << "testFunc2()执行了" << std::endl;
}

// 3
template<typename T,typename... Args>
struct Decay<T(Args...)> // 返回类型是T,参数是Args...
{
	using type = T(*)(Args...);
};

int main()
{
	RemoveCR_t<const int&&> rcrobj = 15; // rcrobj为int类型,只能叹为观止,惊叹rcrobj鬼斧神工地成了int类型

	int arr[2] = { 1,2 };
	Decay<decltype(arr)>::type my_array;
	std::cout << "my_array的类型为: " << typeid(decltype(my_array)).name() << std::endl;

	Decay<decltype(g_array)>::type my_array_2;
	std::cout << "my_array_2的类型为:" << typeid(decltype(my_array_2)).name() << std::endl;

#if 0
	// 2
	Decay<decltype(testFunc2)>::type rfunc;
	std::cout << "rfunc类型为:" << typeid(decltype(rfunc)).name() << std::endl;
	rfunc();
#endif 

	// 3
	Decay<decltype(testFunc2)>::type rfunc_1;
	std::cout << "rfunc类型为:" << typeid(decltype(rfunc_1)).name() << std::endl;
	rfunc_1 = testFunc2;
	rfunc_1();

	return 0;
}

在这里插入图片描述
别名模板的威力
通过别名模板把Decay::type类型名简化成Decay_t,代码如下

template<typename T>
using Decay_t = typename Decay<T>::type;

于是,main()函数中的代码,可以写成

Decay<decltype(testFunc2)>::type rfunc;

就可以写成

Decay_t<decltype(testFunc2)> rfunc;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/224080.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

案例059:基于微信小程序的在线投稿系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

18、XSS——cookie安全

文章目录 1、cookie重要字段2、子域cookie机制3、路径cookie机制4、HttpOnly Cookie机制5、Secure Cookie机制6、本地cookie与内存cookie7、本地存储方式 一般来说&#xff0c;同域内浏览器中发出的任何一个请求都会带上cookie&#xff0c;无论请求什么资源&#xff0c;请求时&…

ubuntu中显卡驱动,cuda,cudnn安装

1. 在ubuntu中安装显卡驱动 参考&#xff1a;https://blog.csdn.net/m0_37605642/article/details/119651996 2.在ubuntu中安装cuda 参考&#xff1a;https://blog.csdn.net/m0_61431544/article/details/127007300 2.1 安装cuda cuda官网&#xff1a; https://developer.n…

配置端口安全示例

组网需求 如图1所示&#xff0c;用户PC1、PC2、PC3通过接入设备连接公司网络。为了提高用户接入的安全性&#xff0c;将接入设备Switch的接口使能端口安全功能&#xff0c;并且设置接口学习MAC地址数的上限为接入用户数&#xff0c;这样其他外来人员使用自己带来的PC无法访问公…

基于单片机出租车计价器控制系统

**单片机设计介绍&#xff0c;基于单片机出租车计价器控制系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的出租车计价器控制系统是一个用于控制和管理出租车费用计算的电子设备。下面是一个简单的系统设计介绍&…

【若依系列】1.项目修改成自己包名并启动服务

项目下载地址&#xff1a; 分离版本 https://gitee.com/y_project/RuoYi-Vue 修改工具下载 https://gitee.com/lpf_project/common-tools 相关截图&#xff1a; 1.项目结构&#xff1a; 2.修改包名工具&#xff1a; 工具截图&#xff0c;根据对应提示自定义修改即可&#x…

HarmonyOS4.0从零开始的开发教程08构建列表页面

HarmonyOS&#xff08;六&#xff09;构建列表页面 List组件和Grid组件的使用 简介 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“首页”页面中包含两个网格布局&#xff…

为何开展数据清洗、特征工程和数据可视化、数据挖掘与建模?

1.2为何开展数据清洗、特征工程和数据可视化、数据挖掘与建模 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.2节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学…

AWS基于x86 vs Graviton(ARM)的RDS MySQL性能对比

概述 这是一个系列。在前面&#xff0c;我们测试了阿里云经济版&#xff08;“ARM”&#xff09;与标准版的性能/价格对比&#xff1b;华为云x86规格与ARM&#xff08;鲲鹏增强&#xff09;版的性能/价格对比。现在&#xff0c;再来看看AWS的ARM版本的RDS情况 在2018年&#…

深度学习猫狗分类 - python opencv cnn 计算机竞赛

文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习猫狗分类 ** 该项目较为新颖&a…

华为配置流量抑制示例

如拓扑图所示&#xff0c;SwitchA作为二层网络到三层路由器的衔接点&#xff0c;需要限制二层网络转发的广播、未知组播和未知单播报文&#xff0c;防止产生广播风暴&#xff0c;同时限制二三层网络转发的已知组播和已知单播报文&#xff0c;防止大流量冲击。 配置思路 用如下…

gpt1与bert区别

区别1&#xff1a;网络结构&#xff08;主要是Masked Multi-Head-Attention和Multi-Head-Attention&#xff09; gpt1使用transformer的decoder&#xff0c;单向编码&#xff0c;是一种基于语言模型的生成式模型&#xff0c;更适合生成下一个单词或句子 bert使用transformer的…

Vue 父传子组件传参 defineProps

defineProps 属性&#xff1a;用于接收父组件传递过来的数据。 注意&#xff1a;如果 defineProps 接收的参数名&#xff0c;和已有变量名相同&#xff0c;就会造成命名冲突。 语法格式&#xff1a; // 无限制 const props defineProps([参数名, 参数名]);// 限制数据类型 …

Spring Boot 项目的创建、配置文件、日志

文章目录 Spring Boot 优点创建 Spring Boot 项目创建项目认识目录网页创建&#xff08;了解&#xff09; 约定大于配置Spring Boot 配置文件配置文件格式读取配置项properties 配置文件yml 配置文件基本语法进阶语法配置对象配置集合yml 设置不同环境的配置文件 Spring Boot 日…

springboot——自动装配

自动装配 Condition: Condition内置方法&#xff1a;boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)&#xff0c;返回值为布尔型 重写matches方法的类&#xff1a;SpringBootCondition等 SpringBootCondition&#xff1a;springboot自带的实现类…

QT5.4.1无法打开文件

问题描述&#xff1a;起初是在QT代码中运行打开文件代码&#xff1a; QString gFilename QFileDialog::getOpenFileName(this,"open File",path,"*", nullptr,QFileDialog::DontUseNativeDialog);时&#xff0c;出现了堵塞情况&#xff0c;经过多次实验一…

Qt进程和线程

一、进程 在设计一个应用程序时,有时不希望将一个不太相关的功能集成到程序中,或者是因为该功能与当前设计的应用程序联系不大,或者是因为该功能已经可以使用现成的程序很好的实现了,这时就可以在当前的应用程序中调用外部的程序来实现该功能,这就会使用到进程。Qt应用程序…

go语言 | etcd源码导读(一)

参考 本文参考https://zhuanlan.zhihu.com/p/600893553 https://www.topgoer.com/%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C/go%E6%93%8D%E4%BD%9Cetcd/etcd%E4%BB%8B%E7%BB%8D.html 前沿etcd 与 raft etcd是使用Go语言开发的一个开源的、高可用的分布式key-value存储系…

分享“技艺与传承”的魅力!春城晚报(开屏新闻)生活节第七期媒体开放日活动举行

近日&#xff0c;由云南报业传媒&#xff08;集团&#xff09;有限责任公司、云南春晚传媒有限公司指导&#xff1b;金格金俊广场、云南精品文化传媒有限公司联合主办的第七期媒体开放日活动在金格金俊广场B1共享空间举办。本次活动以「技艺与传承」为主题&#xff0c;特邀青年…

处理实时视频流:第三方美颜SDK的实时图像处理策略

为了提高用户体验&#xff0c;许多应用和平台开始采用第三方美颜SDK&#xff0c;通过先进的图像处理技术实时改善视频中的面部外观。本文将深入探讨这些第三方美颜SDK在实时视频流处理中所采用的图像处理策略&#xff0c;揭示其背后的技术原理和创新。 一、引言 实时视频流处理…