c++新经典模板与泛型编程:引用类型的移除与增加

引用类型的移除

c++11标准库中提供了一个std::remove_reference类模板,如果传递进来的模板参数是一个引用类型,则会把这个引用类型中的引用部分删除,先看一下用法:


#include <iostream>

template<class T1,class T2>
void print_is_same()
{
	std::cout << "T1 类型为: " << typeid(T1).name() << std::endl;
	std::cout << "T2 类型为: " << typeid(T2).name() << std::endl;

	// 值为1 表示两个类型相等,值为0表示两个类型不等,is_same是标准库中用于判断两个类型是否相等
	// 的类模板,写成std::is_same<T1,T2>::value效果也是一样。
	// std::is_same<T1,T2>()这种写法产生了is_same<T1,T2>的临时对象,而且调用了该类模板的类型
	// 转换运算符把对象转换为了一个整型值输出
	std::cout << "T1 和 T2 类型是否相等: " << std::is_same<T1, T2>() << std::endl;
}


int main()
{

	std::remove_reference<int>::type a;
	std::remove_reference<int&>::type b;
	std::remove_reference<int&&>::type c;

	print_is_same<decltype(a), decltype(b)>();
	print_is_same<decltype(a), decltype(c)>();


	return 0;
}

在这里插入图片描述

我曾经也恬不知耻地认为很熟练C++,说来可笑,来来来,小板凳,咋俩聊聊std::remove_reference源码,哎,咋还没开始,你人跑了,哈哈哈哈(放松,娱乐一下)

另外,`C++14标准中通过别名模板技术定义了大量的别名,例如:

template<class T>
using remove_reference_t = typename remove_reference<T>::type;

所以,前面代码中main()函数里,就可以写的更简便了,可以省略::type

std::remove_reference_t<int> a;
std::remove_reference_t<int&> b;
std::remove_reference_t<int&&> c;

std::remove_reference也是一个trait类模板,想一想,如果要你自己实现一个类似功能,应该怎么写?


#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&&>
{
	using type = T;
};

// 别名模板
template<typename T>
using RemoveReference_t = typename RemoveReference<T>::type;


int main()
{
	int&& a2 = 12;
	// 从报错的结果可以看出来b2的结果已经转成int类型
	// 献上我的膝盖,炸裂啊这里,需要久久反思
	//RemoveReference_t<decltype(a2)> b2 = "dd"; 

	// 注释掉出错的上一行,运行下面的代码
	RemoveReference_t<decltype(a2)> b2 = 125;
	int i = 64;
	int& c2 = i;
	RemoveReference_t<decltype(c2)> d2 = 500;
	
	std::cout << typeid(b2).name() << std::endl;
	std::cout << typeid(d2).name() << std::endl;

	return 0;
}

在这里插入图片描述

引用类型的增加

  1. 所谓引用类型的增加,其实就是根据给定的类型创建一个左值或右值引用。
  2. c++11标准库中提供了一个std::add_lvalue_reference类模板,用于传入一个类型,返回该类型对应的左值引用类型。例如,传入一个int类型,返回int&类型。
  3. c++11也提供了一个std::add_rvalue_reference类模板,用于传入一个类型,返回该类型对应的右值引用类型,例如,传入一个int类型,返回int&&类型。
  4. 相对应地,还有std::is_lvalue_referencestd::is_rvalue_reference类模板,用于判断某个类型是否是左值引用还是右值引用类型。

#include <iostream>

int main()
{
	int a = 15;
	std::add_lvalue_reference<decltype(a)>::type b = a; // b的类型为int&
	std::add_rvalue_reference<decltype(a)>::type c = 16; // c的类型为int&&

	using btype = std::add_lvalue_reference_t<int>; // _t是别名模板
	std::cout << std::is_same<int&, btype>() << std::endl; // 1

	using ctype = std::add_rvalue_reference_t<int>;
	std::cout << std::is_lvalue_reference<btype>::value << std::endl; // 1
	std::cout << std::is_rvalue_reference<ctype>::value << std::endl; // 1

	std::add_rvalue_reference_t<int&> cc1 = a; // cc1的类型为int&,这里涉及到引用折叠: &和&& 折叠得到&
	std::add_rvalue_reference_t<int&&> cc2 = 16; // cc2的类型为int&&,这里涉及引用折叠,&和&& 折叠得到&&


	return 0;
}

在这里插入图片描述

虽然目前没有用到过,但是感觉是个好东西。添加左值和右值引用类型
std::add_lvalue_referencestd::add_rvalue_reference同样都是trait类模板,如果自己来实现类似的功能,你会怎么写?
先写一个增加左值引用类型的类模板


#include <iostream>

template<typename T>
struct AddLValueReference
{
	using type = T&;
};

// 实际上可以直接简化为using AddLValueReference_t = T&; 这样就不用定义AddLValueReference了
template<typename T>
using AddLValueReference_t = typename AddLValueReference<T>::type;


int main()
{
	int anew = 15;
	// decltype(anew)为int类型
	// bnew为int&类型
	AddLValueReference_t<decltype(anew)> bnew = anew; 

	int&& anew2 = 17;
	// decltype(anew2)为int&&类型
	// bnew2为int&类型,引用折叠:有左值引用,结果必然为左值引用,
	AddLValueReference_t<decltype(anew2)> bnew2 = anew2; 
	
	return 0;
}

增加右值引用类型的trait类模板如下:


#include <iostream>

template<typename T>
struct AddRValueReference
{
	using type = T&&;
};

template<typename T>
// 实际上可以直接简化为using AddRValueReference_t = T&&;
// 这样就不要定义AddRValueReference了
using AddRValueReference_t = typename AddRValueReference<T>::type;





int main()
{
	int argnew = 15;
	// brgnew的类型为int&&
	AddRValueReference_t<decltype(argnew)> brgnew = 18;

	int&& argnew2 = 15;
	// brgnew2的类型为int&&,根据引用折叠,两个右值引用遇到一起,结果还是右值引用
	AddRValueReference_t<decltype(argnew2)> brgnew2 = 18;

	int tmpvalue = 16;
	int& argnew3 = tmpvalue;
	// brgnew3的类型是int&
	// 根据引用折叠规则,左值引用和右值引用遇到一起,结果还是左值引用
	AddRValueReference_t<decltype(argnew3)> brgnew3 = tmpvalue;

	
	return 0;
}

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

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

相关文章

Mysql研学-认识与安装

一 数据库 1 Java的数据存储技术 ① 变量:一个数据存储空间的表示 ② 数组:存储一组相同数据类型的"容器" ③ 集合:存储一组任意引用数据类型的"容器" ④ 配置文件: .properties:基于Properties集合存储(Map集合的具体实例) .xml文件:基于标签存储数据…

【精选】设计模式——工厂设计模式

工厂设计模式是一种创建型设计模式&#xff0c;其主要目的是通过将对象的创建过程封装在一个工厂类中来实现对象的创建。这样可以降低客户端与具体产品类之间的耦合度&#xff0c;也便于代码的扩展和维护。 工厂设计模式&#xff1a; 以下是Java中两个常见的工厂设计模式示例…

LCR 090. 打家劫舍 II(leetcode)动态规划

文章目录 前言一、题目分析二、算法原理1.状态表示2.状态转移方程3.初始化4.填表顺序5.返回值是什么 三、代码实现总结 前言 在本文章中&#xff0c;我们将要详细介绍一下LeetcodeLCR 090. 打家劫舍 II。采用动态规划解决&#xff0c;这是一道经典的多状态dp问题 一、题目分析…

Qt开发 之 Qt5各版本情况分析

文章目录 1、简介2、Qt5 版本归纳3、下载地址3.1、典型版本3.1.1、Qt5.0.03.1.2、Qt5.9.93.1.3、Qt5.12.12 3.2、当前Qt5最新版本 1、简介 Qt6 出生刚刚好一年的时间&#xff0c;已经出到6.6版本&#xff0c;带来了许多的新特性和改进。今天刚刚好抽空总结下陪伴 我工作这么长…

【vim】常用操作

用的时候看看&#xff0c;记太多也没用&#xff0c;下面都是最常用的&#xff0c;更多去查文档vim指令集。 以下均为正常模式下面操作&#xff0c;正在编辑的&#xff0c;先etc一下. 1/拷贝当前行 yy&#xff0c;5yy为拷贝包含当前行往下五行 2/p将拷贝的东西粘贴到当前行下…

学习Linux(2)-学习Linux命令

Linux目录结构 Linux目录结构-菜鸟教程 /bin&#xff1a;bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。 /boot&#xff1a;这里存放的是启动 Linux 时使用的一些核心文件&#xff0c;包括一些连接文件以及镜像文件。 /dev &#xff1a;dev 是 De…

【Vue】登录注册界面制作

1. 创建vue项目 https://blog.csdn.net/m0_67930426/article/details/134816155?spm1001.2014.3001.5502 2. 整合element-ui https://blog.csdn.net/m0_67930426/article/details/134827986?spm1001.2014.3001.5502 在view目录下创建文件 本篇内容使用到了 v-model cl…

飞天使-linux操作的一些技巧与知识点3

http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tcp的连接&#xff0c;发起多次http的请求&#xff0c;结束&#xff0c;tcp断开ngi…

企业快递账单管理教程

快递账单管理怎么做&#xff0c;才能更高效&#xff1f;想要回答这个问题&#xff0c;首先我们要了解现如今企业快递账单管理的大致有哪些方式&#xff1a; 1、纸质化管理 纸质化管理现在虽然少见&#xff0c;但是我们应该挺熟悉。在电子面单面试之前&#xff0c;企业快递账单…

go学习笔记(17)Blob and ArrayBuffer

最近在学习go websocket的时候&#xff0c;在学习实验过程遇到一个比较奇怪问题。为什么我的数据返回是blob&#xff0c;而不是arrayBuffer&#xff1f;百思不得其解。 直到同事打包的时候微信小游戏遇到了一个报错。FileReader不支持。 经过在社区查询&#xff0c;官方答复是…

链表OJ—环形链表||

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1、环形链表题目&#xff1a; 2、方法讲解&#xff1a; 图文解析&#xff1a; 代码实现&#xff1a; 其他的两种情况&#xff1a; 总结 前言 世上有两种耀眼的光芒…

leetcode刷题日志-54螺旋矩阵

思路&#xff1a; 上下左右设置四个边界 每走完一行或者一列&#xff0c;移动相应边界&#xff0c;当左边界大于右边界&#xff0c;或者上边界大于下边界时&#xff0c;结束 代码如下&#xff1a; class Solution {public List<Integer> spiralOrder(int[][] matrix) {…

temu我的订单在哪里看

在Temu平台上购物是一件令人愉快的事情&#xff0c;但有时候我们可能会忘记如何查看我们的订单。在本文中&#xff0c;我们将逐步介绍如何在Temu平台上查看您的订单&#xff0c;以便您可以轻松管理您的购物记录。 先给大家推荐一款拼多多/temu运营工具——多多情报通多多情报通…

【Vulnhub 靶场】【Hackable: III】【简单 - 中等】【20210602】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/hackable-iii,720/ 靶场下载&#xff1a;https://download.vulnhub.com/hackable/hackable3.ova 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年06月02日 文件大小&#xff1a;1.6 GB 靶场作者&…

4_CSS选择器进阶

day04_CSS选择器应用 Objective&#xff08;本课目标&#xff09; 掌握复合选择器掌握后代选择器掌握并集选择器掌握标签显示模式和转换掌握CSS背景 1. CSS复合选择器 1.1 后代选择器&#xff08;重点&#xff09; 作用&#xff1a;用来选择元素或元素组的子孙后代 案例 -…

Abaqus Creat Field Output

1、获取应力不变量 s2f33_S.getScalarField(invariantMISES) 2、获得应力分量 s2f33_S.getScalarField(componentLabel"S11") 参考&#xff1a; https://www.eng-tips.com/viewthread.cfm?qid469545

深化适老化服务——建行江门市分行成功打造首家“适老化”服务示范网点

新金融时代&#xff0c;银行物理网点要更好发挥客户面对面接触、情感交互、场景引流、生态建设等功能&#xff0c;开展特色网点建设转型势在必行。 近日&#xff0c;建行江门市分行恩平锦江支行“适老化”服务示范网点开业。走进锦江支行网点大堂&#xff0c;“暖阳港湾”四个…

SAP 批量修改IDOC内容

近第三方系统出现一个问题&#xff0c;导致IDOC发过来的数据都是错误的&#xff0c;但是因为某些原因&#xff0c;无法在第三方系统中重新发起&#xff0c;故需要批量修改IDOC的内容&#xff0c;并且重新在SAP中发起入站 经了解SAP提供了标准的事务代码可以进行简单的IDOC内容…

2023年9月8日 Go生态洞察:gopls的扩展与Go生态系统的成长

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

更改Android Studio的.android和.gradle文件夹默认位置

一、首先关闭Android Studio&#xff0c; 二、目标位置新建文件夹 这一步&#xff0c;为了省去麻烦&#xff0c;我并没有直接在我的目标位置新建文件夹&#xff0c;而是把C盘下的.android和.gradle文件夹整个复制过来&#xff0c;和SDK都在同一目录下&#xff0c;感觉这样可以…
最新文章