突破编程_C++_C++11新特性(type_traits的修改类型特性)

1 type_traits 的修改类型特性

1.1 std::add_const

std::add_const 是一个模板类,用于给类型添加 const 限定符,表示该类型的对象是不可修改的。

定义:

template< class T >  
struct add_const;

样例:

#include <type_traits>  
#include <iostream>  int main() {typedef int MyType;typedef std::add_const<MyType>::type ConstMyType;// 使用std::is_const检查类型是否为const  static_assert(std::is_const<ConstMyType>::value, "Type should be const");// 尝试修改ConstMyType的对象会编译失败  // ConstMyType value = 5;  // value = 10; // 错误:尝试修改const对象  return 0;
}

1.2 std::remove_const

std::remove_const 是一个模板类,用于移除类型的const限定符,使得该类型的对象可以被修改。

定义:

template< class T >  
struct remove_const;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef const int ConstMyType;  typedef std::remove_const<ConstMyType>::type NonConstMyType;  // 使用std::is_const检查类型是否不为const  static_assert(!std::is_const<NonConstMyType>::value, "Type should not be const");  NonConstMyType value = 5;  value = 10; // 正确:NonConstMyType是int,可以修改  return 0;  
}

1.3 std::add_volatile

std::add_volatile 是一个模板类,用于给类型添加 volatile 限定符,这通常用于告诉编译器不要对该类型的对象进行特定的优化,因为它们可能在程序外部被改变。

定义:

template< class T >  
struct add_volatile;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef int MyType;  typedef std::add_volatile<MyType>::type VolatileMyType;  // 使用std::is_volatile检查类型是否为volatile  static_assert(std::is_volatile<VolatileMyType>::value, "Type should be volatile");  // VolatileMyType通常用于与外部硬件交互等场景  // ...  return 0;  
}

1.4 std::remove_volatile

std::remove_volatile 是一个模板类,用于移除类型的 volatile 限定符。

定义:

template< class T >  
struct remove_volatile;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef volatile int VolatileMyType;  typedef std::remove_volatile<VolatileMyType>::type NonVolatileMyType;  // 使用std::is_volatile检查类型是否不为volatile  static_assert(!std::is_volatile<NonVolatileMyType>::value, "Type should not be volatile");  NonVolatileMyType value = 5;  // ...  return 0;  
}

1.5 std::add_pointer

std::add_pointer 是一个模板类,用于给类型添加指针。

定义:

template< class T >  
struct add_pointer;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef int MyType;  typedef std::add_pointer<MyType>::type PointerType;  // 使用std::is_pointer检查类型是否为指针  static_assert(std::is_pointer<PointerType>::value, "Type should be a pointer");  PointerType ptr = new int(5);  // ...  delete ptr;  return 0;  
}

1.6 std::remove_pointer

std::remove_pointer 是一个模板类,用于移除类型的指针。

定义:

template< class T >  
struct remove_pointer;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef int* PointerType;  typedef std::remove_pointer<PointerType>::type NonPointerType;  // 使用std::is_pointer检查类型是否不为指针  static_assert(!std::is_pointer<NonPointerType>::value, "Type should not be a pointer");  NonPointerType value = 5;  // ...  return 0;  
}

1.7 std::add_lvalue_reference

std::add_lvalue_reference 是一个模板类,用于给类型添加左值引用。

定义:

template< class T >  
struct add_lvalue_reference;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef int MyType;  typedef std::add_lvalue_reference<MyType>::type LvalueReferenceType;  // 使用std::is_lvalue_reference检查类型是否为左值引用  static_assert(std::is_lvalue_reference<LvalueReferenceType>::value, "Type should be an lvalue reference");  MyType value = 5;  LvalueReferenceType ref = value; // ref是对value的左值引用  ref = 10; // 实际上修改了value的值  std::cout << value << std::endl; // 输出:10  return 0;  
}

1.8 std::add_rvalue_reference

std::add_rvalue_reference 是一个模板类,用于给类型添加右值引用。

定义:

template< class T >  
struct add_rvalue_reference;

样例:

#include <type_traits>  
#include <iostream>  int main() {  typedef int MyType;  typedef std::add_rvalue_reference<MyType>::type RvalueReferenceType;  // 使用std::is_rvalue_reference检查类型是否为右值引用  static_assert(std::is_rvalue_reference<RvalueReferenceType>::value, "Type should be an rvalue reference");  MyType value = 5;  // 注意:不能直接给左值绑定右值引用,通常用于函数参数或临时对象  RvalueReferenceType&& rvalueRef = std::move(value); // rvalueRef是对value的右值引用(通过std::move转换为右值)  // rvalueRef现在"拥有"value,并可以将其资源"偷走"  return 0;  
}

2 std::add_const 与 std::remove_const 的应用场景

假设需要设计一个模板函数,它接受一个迭代器,并希望根据迭代器所指向的元素的类型来执行某些操作。如果迭代器指向的元素是 const 的,并且想要保留这个 const 特性;如果不是,则需要添加 const 以确保函数内部不会修改元素的值。

#include <iostream>  
#include <vector>  
#include <type_traits>  
#include <iterator>  // 假设有一个函数,它接受一个const引用,并打印元素的值  
template<typename ConstValueType>
void print_value(const ConstValueType& value) {std::cout << value << std::endl;
}// 一个通用函数,处理迭代器指向的元素,可能添加const  
template<typename It>
void process_element(It it) {typedef typename std::iterator_traits<It>::value_type ValueType;typedef typename std::add_const<ValueType>::type ConstValueType;// 使用const引用调用print_value,确保不会修改元素的值  print_value(*it);
}int main() 
{// 创建一个可修改的vector  std::vector<int> modifiable_vec = { 1, 2, 3 };// 创建一个const vector  const std::vector<int> const_vec = { 4, 5, 6 };// 使用非const迭代器调用process_element  process_element(modifiable_vec.begin()); // 输出: 1  // 尝试修改vector的元素(这是允许的,因为迭代器不是const)  modifiable_vec[0] = 10;// 使用const迭代器调用process_element  process_element(const_vec.begin()); // 输出: 4  // 尝试修改const vector的元素(这将导致编译错误)  // const_vec[0] = 20; // 编译错误:尝试修改const对象  return 0;
}

上面代码的输出为:

1
4

在这个示例中,process_element 函数是一个模板函数,它接受一个迭代器 It。通过使用 std::iterator_traits,可以获取迭代器所指向的元素的类型 ValueType。然后,使用 std::add_const 来创建一个新的类型 ConstValueType,它是 ValueType 的 const 版本。

这个示例定义了一个辅助函数 print_value,它接受一个 const 引用,并打印元素的值。在 process_element 函数内部,使用 const 引用调用 print_value,确保即使传入的迭代器指向的是可修改的元素,我们也不会在函数内部修改它。

这个示例展示了如何使用 std::add_const 来确保函数内部的操作不会意外地修改传入的元素。当然,如果确实需要修改元素的值,可以使用 std::remove_const 来移除 const 限定符,但这通常是不推荐的,除非你非常确定这样做是安全的。在大多数情况下,保持对元素的 const 引用是更好的选择,因为它能防止无意的修改,并增加代码的安全性。

3 std::add_pointer 与 std::remove_pointer 的应用场景

假设需要设计一个泛型函数,它接受一个类型 T,并需要根据这个类型来执行某些操作。有时候,可能需要处理 T 的指针类型,有时候则需要处理 T 本身。使用 std::add_pointer 和 std::remove_pointer 可以方便地在这两种类型之间转换。

#include <iostream>  
#include <type_traits>  // 一个函数模板,它接受一个类型T,并打印T是否是指针类型  
template <typename T>
void print_is_pointer() {std::cout << std::boolalpha << std::is_pointer<T>::value << std::endl;
}// 一个函数模板,它接受一个类型T,并返回T的指针类型  
template <typename T>
typename std::add_pointer<T>::type get_pointer() {static T value;return &value;
}// 一个函数模板,它接受一个类型T的指针,并返回T本身  
template <typename T>
typename std::remove_pointer<T>::type* get_value(T ptr) {return ptr;
}int main() 
{// 示例:int类型  int i = 0;std::cout << "int is pointer? ";print_is_pointer<int>(); // 输出: false  int* pi = &i;std::cout << "int* is pointer? ";print_is_pointer<int*>(); // 输出: true  // 使用get_pointer来获取int的指针  int* pi_from_func = get_pointer<int>();std::cout << "Value from get_pointer<int>: " << *pi_from_func << std::endl; // 输出: 0  // 示例:int*类型  std::cout << "int* is pointer? ";print_is_pointer<decltype(pi)>(); // 输出: true  // 使用get_value来获取int*指向的值  int* pi_copy = get_value(pi);std::cout << "Value from get_value(pi): " << *pi_copy << std::endl; // 输出: 0  return 0;
}

上面代码的输出为:

int is pointer? false
int* is pointer? true
Value from get_pointer<int>: 0
int* is pointer? true
Value from get_value(pi): 0

在这个示例中:

  • print_is_pointer 函数模板用于打印类型 T 是否是指针类型。
  • get_pointer 函数模板接受一个类型 T,并返回 T 的指针类型的一个静态实例的地址。这允许我们即使对于非指针类型,也能得到一个指向该类型实例的指针。
  • get_value 函数模板接受一个类型 T 的指针,并返回该指针本身(实际上是返回 T 类型的指针)。这演示了如何从指针类型中提取原始类型。

这个示例展示了如何结合使用 std::add_pointer 和 std::remove_pointer 来处理指针和非指针类型。在泛型编程中,这样的转换是常见的,尤其是在需要统一处理引用、值以及它们的指针形式时。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

性能测试如何定位分析性能瓶颈?

对于一般公司普通测试工程师来说&#xff0c;可能性能测试做的并不是很复杂&#xff0c;可能只是编写下脚本&#xff0c;做个压测&#xff0c;然后输出报告结果&#xff0c;瓶颈分析和调优的事都丢给开发去做。 在一些大厂都有专门的性能测试团队去定位分析系统性能瓶颈&#…

每日OJ题_子数组子串dp⑤_力扣413. 等差数列划分

目录 力扣413. 等差数列划分 解析代码 力扣413. 等差数列划分 413. 等差数列划分 难度 中等 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。 例如&#xff0c;[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等…

流畅切换Linux的应用程序

流畅切换Linux的应用程序 流畅切换Linux的应用程序一.Linux启动一个程序在后台执行1. 使用nohup和&&#xff1a;2. 使用ctrlZ&#xff1a;3.使用screen&#xff1a;3.1 创建会话3.2 要重新连接到此会话&#xff1a;3.3 中途退出会话&#xff0c;但程序继续运行:3.4 结束一个…

第十节HarmonyOS 常用容器组件3-GridRow

1、描述 栅格容器组件&#xff0c;仅可以和栅格子组件&#xff08;GridCol&#xff09;在栅格布局场景中使用。 2、子组件 可以包含GridCol子组件。 3、接口 GridRow(options:{columns: number | GridRowColumnOption, gutter?: Length | GutterOption, Breakpoints?: B…

把 Taro 项目作为一个完整分包,Taro项目里分包的样式丢失

现象&#xff1a; 当我们把 Taro 项目作为原生微信小程序一个完整分包时&#xff0c;Taro项目里分包的样式丢失&#xff0c;示意图如下&#xff1a; 原因&#xff1a; 在node_modules/tarojs/plugin-indie/dist/index.js文件里&#xff0c;限制了只有pages目录下会被引入app.w…

Springboot实现qq邮件的发送

一、打开必要的邮件设置 首先登录qq邮箱官网登录之后&#xff0c;在设置中将传输协议给打开&#xff0c;我们需要用这个秘钥作为发件人的邮箱授权。 这里开启之后&#xff0c;记住这个秘钥。 二、代码编写 首先我们将作为发送邮件的账户信息写入配置文件。 spring:mail:hos…

windows server 下的mysql 8.0.28修改数据库目录

1. 查看当前数据库存储位置 show global variables like %datadir%; 默认是&#xff1a;C:\ProgramData\MySQL\MySQL Server 8.0\Data 2. 修改 C:\ProgramData\MySQL\MySQL Server 8.0\my.ini配置文件。如下&#xff1a; datadirD:/ProgramData/MySQL/MySQL Server 8.0/Dat…

小兴教你做平衡小车-JGB37-520电机介绍

文章目录 1 前言2 分析电机安装板3 介绍电机驱动板3.1 电机驱动板原理图3.2 电机驱动板PCB图3.2 电机驱动板3D效果图 1 前言 为了更好的对JGB37-520这款电机有个了解&#xff0c;这里直接上图应该会清晰些。这款电机带有霍尔编码器&#xff0c;方便对车轮的转速进行采集。咱们…

vulnhub-----pWnOS1.0靶机

文章目录 1.信息收集2.漏洞测试3.爆破hash4.提权 首先拿到一台靶机&#xff0c;就需要知道靶机的各种信息&#xff08;IP地址&#xff0c;开放端口&#xff0c;有哪些目录&#xff0c;什么框架&#xff0c;cms是什么&#xff0c;网页有什么常见的漏洞&#xff0c;如sql注入&…

第2讲-Memory(3)主存

主存储器 多模块存储器

数据库系统概论-第16章 数据仓库与联机分析处理技术

概念性的介绍&#xff0c;一略而过&#xff0c;不重要。 16.1 数据仓库技术 16.2 联机分析处理技术 16.3 数据挖掘技术 16.4 大数据时代的新型数据仓库 16.5 小结

3d画线生成模型之后最大化找不到---模大狮模型网

当你在3D建模软件中画线生成模型后&#xff0c;如果最大化找不到该模型&#xff0c;可能是因为以下几种情况导致&#xff1a; 模型位置偏移&#xff1a; 可能你在绘制线条时&#xff0c;将模型画在了视图界面之外&#xff0c;导致最大化时无法看到。尝试平移或旋转模型&#x…

vue3中如何实现多个侦听器(watch)

<body> <div id"app"><input type"button" value"更改名字" click"change"> </div> <script src"vue.js"></script> <script>new Vue({el: #app,data: {food: {id: 1,name: 冰激…

MySQL中行锁、表锁、悲观锁、乐观锁和共享锁

在操作数据库的时候&#xff0c;可能会由于并发问题而引起的数据的不一致性&#xff08;数据冲突&#xff09;&#xff0c;如何保证数据并发访问的一致性、有效性&#xff0c;是所有数据库必须解决的一个问题&#xff0c;锁的冲突也是影响数据库并发访问性能的一个重要因素&…

大模型开发框架langchain系列教程

LangChain 是一种框架&#xff0c;借助 LangChain&#xff0c;与大语言模型的交互变得更加便捷。 LangChain 提供的接口和功能有助于将 LLM 的强大能力轻松集成到你的工作应用程序中。 我做了一个langchain的教程系列&#xff0c;详情请看&#xff1a; 大模型应用框架LangChai…

透视未来工厂:山海鲸可视化打造数字孪生新篇章

在信息化浪潮的推动下&#xff0c;数字孪生工厂项目正成为工业制造领域的新宠。作为一名山海鲸可视化的资深用户&#xff0c;我深感其强大的数据可视化能力和数字孪生技术在工厂管理中的应用价值&#xff0c;同时我们公司之前也和山海鲸可视化合作制作了一个智慧工厂项目&#…

Matlab与高光谱遥感:环境监测的新时代

光谱和图像是人们观察世界的两种方式&#xff0c;高光谱遥感通过“图谱合一”的技术创新将两者结合起来&#xff0c;大大提高了人们对客观世界的认知能力&#xff0c;本来在宽波段遥感中不可探测的物质&#xff0c;在高光谱遥感中能被探测。以高光谱遥感为核心&#xff0c;构建…

Python实战:日志记录与调试技巧

一、引言 在软件开发过程中&#xff0c;日志记录和调试是确保代码质量和效率的关键。日志记录可以帮助我们记录和分析程序的运行情况&#xff0c;而调试则是找出和修复程序中的错误。Python作为一种广泛使用的编程语言&#xff0c;提供了丰富的日志记录和调试工具。本文将详细…

“postinstall“: “patch-package“ 修补安装包补丁

在 package.json 文件里&#xff0c;postinstall 是一个钩子脚本&#xff0c;它在每次运行 npm install 命令后自动执行。当你在该字段中指定 "patch-package" 时&#xff0c;意思是在 npm install 安装所有依赖包之后&#xff0c;自动运行 patch-package 命令。 pa…

【Python模块】

Python模块是一个包含Python定义和语句的文件。 模块可以定义函数、类和变量。 模块也可以包含可执行的代码。一个模块就是一个包含Python代码的文件&#xff0c;文件后缀是.py。模块可以被其他程序引入&#xff08;import&#xff09;&#xff0c;以使用该模块中的函数等功能…