Effective C++ 规则47: 请使用 Traits Class 表现类型信息
1、背景
C++ 是一种静态类型语言,类型的特性在编译期就可以被识别和操作。为了更好地利用编译期信息来编写高效、灵活、可维护的代码,C++ 提供了一些技术来“萃取”或“提取”类型的相关信息。即利用 traits 类来封装和提取类型信息,以便在编译期进行各种类型相关的判断和操作。Traits Class(类型萃取类)是一个用来提取类型信息的模板类。通过 traits class,我们可以在编译期获得类型的各类信息,并根据这些信息在模板代码中进行分支选择或优化。traits class 通过模板特化的方式来为不同类型提供不同的行为。通常,traits class 会定义一组静态成员(比如 value 或 type),这些成员可以在编译期提供类型的属性或特征。
2、Traits Class 的基本原理
一个 traits class 一般是通过模板类来实现的,模板类通过特化为不同类型提供不同的行为。下面是一个简单的例子,定义了一个判断类型是否为指针的 traits class:
// 默认情况下,假设 T 不是指针
template <typename T>
struct is_pointer {static const bool value = false;
};// 特化:如果 T 是指针类型,则 value 为 true
template <typename T>
struct is_pointer<T*> {static const bool value = true;
};
使用 is_pointer traits class 来判断一个类型是否为指针:
#include <iostream>int main() {std::cout << is_pointer<int>::value << std::endl; // 输出 0(false)std::cout << is_pointer<int*>::value << std::endl; // 输出 1(true)return 0;
}
在上面的代码中:
- is_pointer 是一个 traits class,用来判断某个类型是否为指针类型。
- 对于类型 int,它的特化版本的 value 为 false,表示 int 不是指针。
- 对于类型 int*,它的特化版本的 value 为 true,表示 int* 是指针类型。
3、为什么要使用Traits Class
在 C++ 模板编程中,我们常常需要为不同的类型编写通用的代码。然而,某些类型可能具有不同的行为,或者某些操作在某些类型上可能不可行。此时,使用 traits class 可以让我们在编译期根据类型的不同特性做出不同的决策,从而使得模板代码更加灵活且高效。
- 编译期类型信息,通过 traits class,我们可以在编译期获得类型的各种信息,如是否为指针、是否为容器、是否为数值类型等。通过这些信息,可以在编译期做出决定,而无需在运行时进行计算。
- 增强的模板特化,C++ 中的模板特化使得我们可以为不同的类型提供不同的实现。traits class 是实现这种特化的一种常用方式。通过 traits,我们可以在不同类型之间做出灵活的分支,而不必为每种类型都写一个完整的模板特化版本。
- 提高代码的通用性和可维护性,使用 traits class 可以大大提高模板代码的通用性,使得我们能够以一种更加通用的方式处理不同的类型,而不需要手动处理每种类型的特殊情况。此外,traits class 也使得代码更加易于维护,因为类型的特性被集中管理,并且通过静态成员变量可以快速查看和修改。
4、使用 Traits Class 的实际案例
- 提取类型的元素类型,假设我们有一个容器类型 std::vector,我们想要从容器中提取元素类型。我们可以使用 traits class 来实现这一目标:
// 定义一个 traits class 来提取容器类型的元素类型
template <typename T>
struct element_type {typedef typename T::value_type type;
};// 使用示例
#include <vector>
#include <iostream>int main() {typedef std::vector<int> Vec;typedef element_type<Vec>::type ElementType;ElementType x = 10; // ElementType 被推导为 intstd::cout << x << std::endl; // 输出 10return 0;
}
在这个例子中,我们定义了 element_type traits class,它通过 T::value_type 提取了容器 T 中存储的元素类型。对于 std::vector,element_type::type 被推导为 int。
- 类型特化与分支选择,我们可以使用 traits class 来为不同类型实现不同的行为:
#include <iostream>
#include <type_traits>// 默认版本
template <typename T>
void print_type(const T& x) {std::cout << "Non-pointer: " << x << std::endl;
}// 特化版本:处理指针类型
template <typename T>
void print_type(T* x) {std::cout << "Pointer: " << *x << std::endl;
}int main() {int a = 10;int* p = &a;print_type(a); // 输出:Non-pointer: 10print_type(p); // 输出:Pointer: 10return 0;
}
在这个例子中,我们定义了两个 print_type 函数,一个是处理非指针类型的版本,另一个是处理指针类型的版本。通过 traits class 和模板特化,编译器可以根据参数的类型自动选择合适的函数版本。
5、Traits Class 与现代 C++
现代 C++(特别是 C++11 及以后版本)提供了更多的功能和工具,使得 traits class 更加强大和灵活。例如,C++11 引入了 constexpr 和 type_traits 库,后者提供了大量常用的类型 traits,如 std::is_pointer、std::is_integral 等。使用标准库中的traits
#include <type_traits>
#include <iostream>int main() {std::cout << std::is_pointer<int>::value << std::endl; // 输出 0(false)std::cout << std::is_pointer<int*>::value << std::endl; // 输出 1(true)return 0;
}
在这个例子中,标准库的 std::is_pointer traits 用来判断一个类型是否是指针类型,它们的工作方式与我们自己实现的 traits 类似,但更强大和丰富。
相关文章:
Effective C++ 规则47: 请使用 Traits Class 表现类型信息
1、背景 C 是一种静态类型语言,类型的特性在编译期就可以被识别和操作。为了更好地利用编译期信息来编写高效、灵活、可维护的代码,C 提供了一些技术来“萃取”或“提取”类型的相关信息。即利用 traits 类来封装和提取类型信息,以便在编译期…...
媒体新闻发稿要求有哪些?什么类型的稿件更好通过?
为了保证推送信息的内容质量,大型新闻媒体的审稿要求一向较为严格。尤其在商业推广的过程中,不少企业的宣传稿很难发布在这些大型新闻媒体平台上。 媒体新闻发稿要求有哪些?就让我们来了解下哪几类稿件更容易过审。 一、媒体新闻发稿要求有哪…...
“AI教学实训系统:打造未来教育的超级引擎
嘿,各位教育界的伙伴们,今天我要跟你们聊聊一个绝对能让你们眼前一亮的教学神器——AI教学实训系统。作为资深产品经理,我可是亲眼见证了这款系统如何颠覆传统教学,成为未来教育的超级引擎。 一、什么是AI教学实训系统?…...
基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
【2024年华为OD机试】(A卷,200分)- 查找树中元素 (JavaScriptJava PythonC/C++)
一、问题描述 题目解析 题目描述 题目要求根据输入的坐标 (x, y) 在树形结构中找到对应节点的内容值。其中: x 表示节点所在的层数,根节点位于第0层,根节点的子节点位于第1层,依此类推。y 表示节点在该层内的相对偏移,从左至右,第一个节点偏移为0,第二个节点偏移为1,…...
Pyecharts图表交互功能提升
在数据可视化中,交互功能可以极大地提升用户体验,让用户能够更加深入地探索数据。Pyecharts 提供了多种强大的交互功能,本篇将重点介绍如何使用缩略轴组件、配置图例交互,让我们的数据可视化作品更加生动有趣。 一、缩略轴组件使…...
用layui表单,前端页面的样式正常显示,但是表格内无数据显示(数据库连接和获取数据无问题)——已经解决
这是我遇到的错误 原因:后端控制台的数据格式没有设置清楚 解决:1、加注释 ResponseBody ,确保返回的是json数据。 2、要传三个参数到前端,如下图第二个红色框框所示。因为layui框架代码如果未修改,默认要传入这三个…...
单片机基础模块学习——按键
一、按键原理图 当把跳线帽J5放在右侧,属于独立按键模式(BTN模式),放在左侧为矩阵键盘模式(KBD模式) 整体结构是一端接地,一端接控制引脚 之前提到的都是使用了GPIO-准双向口的输出功能&#x…...
elk 安装
创建elk网络 docker network create -d bridge elkelasticsearch 创建目录 mkdir -p /data/elasticsearch/{conf,logs,data,plugins}vim /data/elasticsearch/conf/elasticsearch.ymlcluster.name: "es-cluster" network.host: 0.0.0.0 xpack.security.enabled: tr…...
2025年1月22日(什么是扫频)
扫频(Sweep Frequency)是一种信号处理技术,通常用于系统识别、频率响应分析和特性测试。它通过发送一个频率逐渐变化的信号(通常是正弦波或线性调频信号)来激励系统,然后测量系统的响应。这种方法可以帮助我…...
mybatis是什么?有什么作用?mybatis的简单使用
mybatis是什么? MyBatis 是一个持久层框架。 有什么作用? 简化了对数据库数据的操作。 如何简化数据操作的? MyBatis 通过提供 SQL 映射、动态 SQL、结果映射、事务管理等功能,我们直接去用就可以了。 怎么使用?&…...
webpack 打包自己的--windows
第一步安装node 1、安装nodejs:https://nodejs.org/zh-cn/download/releases/ 一、Window系统配置: 打开命令窗口,进入当前工程目录 npm配置淘宝镜像:npm config set registry http://registry.npm.taobao.org/ npm安装parcel-bundler:npm install -g parcel-bund…...
微服务学习-Nacos 注册中心实战
1. 注册中心的设计思路 1.1. 微服务为什么会用到注册中心? 服务与服务之间调用需要有服务发现功能;例如订单服务调用库存服务,库存服务如果有多个,订单服务到底调用那个库存服务呢(负载均衡器)࿰…...
MySQL数据库 - 语法知识
一 数据模型 1 关系型数据库管理系统(RDBMS) 概念:建立在关系模型基础上,有多张相互连接的二维表组成的数据库。 特点: 使用表存储数据,格式统一,便于维护。使用SQL语言操作,标准…...
Zookeeper(28)Zookeeper的线性化写入和顺序一致性读是什么?
Zookeeper 是一个分布式协调服务,它在设计上提供了强一致性的保证,其中包括线性化写入和顺序一致性读。这两种一致性模型确保了在分布式系统中数据的一致性和操作的确定性。 线性化写入(Linearizable Writes) 线性化写入保证在任…...
kamailio-5.8.4-centos9编译
安装必要的依赖包 在开始编译之前,你需要安装编译 Kamailio 所需的一些基础依赖包: dnf install -y make gcc gcc-c flex bison libxml2-devel openssl-devel sqlite-devel mysql-devel pcre-devel libcurl-devel下载并解压 Kamailio 源码包 假设你已经…...
有限元分析学习——Anasys Workbanch第一阶段笔记(15)接触间隙处理与赫兹接触
目录 0 序言 1 接触的间隙处理 1.1 结果对比 1.2 处理方法 2 赫兹接触 0 序言 本章主要介绍间隙出现时的三种解决方法,齿轮点蚀/表面剥落涉及的赫兹接触的一些理论知识。 1 接触的间隙处理 在实际产品过程中,很多时候由于设计问题,原本…...
Angular 2 表单深度解析
Angular 2 表单深度解析 引言 Angular 2作为现代前端开发的框架之一,以其灵活性和强大的功能赢得了众多开发者的青睐。在Angular 2中,表单处理是其中一个重要且复杂的部分。本文将深入解析Angular 2的表单,从基础知识到高级应用,旨在帮助开发者更好地理解和运用Angular 2…...
查询本周一到周五的数据
查询sql SELECT CASEWHEN TO_CHAR(T.BEGINDATE, D) 2 THEN 周一WHEN TO_CHAR(T.BEGINDATE, D) 3 THEN 周二WHEN TO_CHAR(T.BEGINDATE, D) 4 THEN 周三WHEN TO_CHAR(T.BEGINDATE, D) 5 THEN 周四WHEN TO_CHAR(T.BEGINDATE, D) 6 THEN 周五END AS DAY_NAME,T.COLUMN1,T.COL…...
【Linux】命令为桥,存在为岸,穿越虚拟世界的哲学之道
文章目录 Linux基础入门:探索操作系统的内核与命令一、Linux背景与发展历史1.1 Linux的起源与发展1.2 Linux与Windows的对比 二、Linux的常用命令2.1 ls命令 - "List"(列出文件)2.2 pwd命令 - "Print Working Directory"(…...
【技术】TensorRT 10.7 安装指南(Ubuntu22.04)
原文链接:https://mengwoods.github.io/post/tech/008-tensorrt-installation/ 本文安装的版本如下: Ubuntu 22.04 Nvidia Driver 538.78 CUDA 12.2 cuDNN 8.9.7 TensorRT 10.7 安装前的准备(可选) 在安装新版本之前…...
2025美赛美国大学生数学建模竞赛A题完整思路分析论文(43页)(含模型、可运行代码和运行结果)
2025美国大学生数学建模竞赛A题完整思路分析论文 目录 摘要 一、问题重述 二、 问题分析 三、模型假设 四、 模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1样例代码(仅供参考) 4.1.4问题1样例代码运行结果&…...
DDD架构实战第七讲总结:分层模型和代码组织
云架构师系列课程之DDD架构实战第七讲总结:分层模型和代码组织 一、引言 在前几讲中,我们介绍了领域驱动设计(DDD)的基本构造块和生命周期模型中的聚合。本讲将重点讨论如何将这些构造块和代码组织起来,探讨分层架构和六边形模型,以及如何组织代码结构。 二、工厂和资…...
http的请求体各项解析
一、前言 做Java开发的人员都知道,其实我们很多时候不单单在写Java程序。做的各种各样的系统,不管是PC的 还是移动端的,还是为别的系统提供接口。其实都离不开http协议或者https 这些东西。Java作为编程语言,再做业务开发时&#…...
深入探究分布式日志系统 Graylog:架构、部署与优化
文章目录 一、Graylog简介二、Graylog原理架构三、日志系统对比四、Graylog部署传统部署MongoDB部署OS或者ES部署Garylog部署容器化部署 五、配置详情六、优化网络和 REST APIMongoDB 七、升级八、监控九、常见问题及处理 一、Graylog简介 Graylog是一个简单易用、功能较全面的…...
微信开发者工具的快捷键
微信开发者工具的快捷键 微信开发者工具的所有快捷键...
MySQL 中的递归查询:实现与优化
在处理层次结构数据(如组织架构、分类树、评论回复等)时,递归查询是不可或缺的工具。MySQL 8.0 版本引入了对递归公用表表达式(Common Table Expressions, CTEs)的支持,使得我们可以更加直观和高效地编写递…...
科家多功能美发梳:科技赋能,重塑秀发新生
在繁忙的都市生活中,头皮健康与秀发养护成为了现代人不可忽视的日常课题。近日,科家电动按摩梳以其卓越的性能和创新设计,赢得了广大消费者的青睐。这款集科技与美学于一身的美发梳,不仅搭载了2亿负离子、6000次/分钟的声波振动等前沿技术,更融入了650nm聚能环红光与415nm强劲蓝…...
JVM面试题解,垃圾回收之“分代回收理论”剖析
一、什么是分代回收 我们会把堆内存中的对象间隔一段时间做一次GC(即垃圾回收),但是堆内存很大一块,内存布局分为新生代和老年代、其对象的特点不一样,所以回收的策略也应该各不相同 对于“刚出生”的新对象…...
批量修改图片资源的属性。
Unity版本2022.3 如图,比如我们想要修改图片的属性的时候,大部分都是 TextureImporter importer (TextureImporter)AssetImporter.GetAtPath("Assets/1.png"); // 获取文件 importer.xxxxxxx xxxxxxx; // 修改属性到这里没什么问题…...
