C++traits

traits

C++的标准库提供了<type_traits>,它定义了一些编译时基于模板类的接口用于查询、修改类型的特征:输入的时类型,输出与该类型相关的属性
通过type_traits技术编译器可以回答一系列问题:它是否为数值类型?是否为函数对象?是不是指针?有没有构造函数?能不能拷贝构造等等
type_traits技术还能对类型进行变换,比如给定的类型任意T,能为这个类型添加const修饰符、添加引用或指针等。而这一切都发生在编译时,过程中没有任何运行时开销

判断类别

谓词命名以is_为前缀,通过访问静态成员常量value得到输出结果

static_assert(std::is_integral<int>::value);//true
static_assert(! std::is_integral<float>::value);//false
static_assert(std::is_floating_point<double>::value);//true
static_assert(std::is_class<struct Point>::value);//true
static_assert(!std::is_same<int , long>::value);//false

is_integral用来判断给定的类型是否为整数类型,使用尖括号将类型输出给这个trait,通过其成员valu来输出一个bool类型的结果
is_floating_point用来判断给定的类型是否为浮点类型
is_class用来判断给定的类型是否为class、struct定义的类型
is_same用来判断给定的两个类型是否为相同类型


对于一个type traits谓词的结果,标准库约定使用value常量来存储,C++17为其预定义了一系列模板,::value的访问方式能够用_v来代替

template <typename T>constexpr bool is_integral_v = is_integral<T>::value;
template <typename T>constexpr bool is_class_v = is_class<T>::value;

类型变换

标准库有些typed traits拥有修改类型的能力:基于已有类型应用修改得到新的类型,输出类型可以通过访问type类型成员函数得到结果。

类型修改不会原地修改输入的类型,而是产生新的类型以应用这些修改

static_assert(is_same_v<typename std::remove_const<const int>::type , int>);
static_assert(is_same_v<typename std::remove_const<int>::type , int>);
static_assert(is_same_v<typename std::add_const<int>::type ,const int>);
static_assert(is_same_v<typename std::add_pointer<int **>::type , int ***>);
static_assert(is_same_v<typename std::decay<int[5][6]>::type , int(*)[6]>);

remove_const将输入的类型移除掉const修饰符并返回新的类型,如果不带const则不变
add_const将输入的类型添加const修饰符
add_pointer为输入的类型添加一级指针
decay语义为退化通过模拟函数或值语义传递时会使所有应用到的函数参数类型退化,若为引用那么应用将会去掉


在C++11引入类型别名using后typename decay<int[5] [6]>::type可变为decay_t<int[5] [6]>
下面是标准库定义的一些类型别名

template<typename T>using remove_const_t = typename remove_const<T>::type;
template<typename T>using decay_t = typename decay<T>::type;

辅助类

辅助类integral_constant将值与对应的类型包裹起来,从而能够将值转化为类型,也能从类型转换回值,实现值与类型的一一映射关系
这个类的主要作用是作为一个容器,用于存储在编译时就可以确定的值,并且这个值的类型也是在编译期可知的。

using Two = std::integral_constant<int,2>;
using Four = std::integral_constant<int,4>;
static_assert(Two::value * Two::value == Four::value);

Tow和Four为两个类型,分别对应2,4。使用integral_constant将值转换成类型后通过value静态成员常量从类型中得到值并进行计算


标准库对应布尔类型也提供了bool_constant,实现时仅仅是integral_constant的类型别名

template<bool v>using bool_constant = integral_constant<bool , v>;

将这两个值映射成类型

uaing true_type = integral_constant<bool , true>;
uaing false_type = integral_constant<bool , false>;

enable_if

enable_if常出现于SFINAE场景中,通过对模板函数,模板类中的类型进行谓词判断,使得程序能够选择合适的模板函数的重载版本或模板类的特化版本
enable_if可接受两个模板参数,第一个参数为bool类型的值,当条件为真时输出的类型成员type的结果为第二个模板参数,否则没有类型成员type

int a;
typename std::enable_if<a == 1,int>::type *a;  //当a==1时,condition为true,那么type为int,所以会声明一个int* a;
typename std::enable_if<!(a == 1),double>::type *a;  //a !=1时,condition为true,那么type为double,所以会声明一个double* a;

enable_if用于函数模板中,典型应用是作为函数模板的返回类型

template<typename T>
typename std::enable_if<(sizeof(T) > 2)>::type funceb()
{
    //....
}
nmsp2::funceb<int>();//void funceb(){}
nmsp2::funceb<char>();//error:未找到匹配的重载函数,条件不满足

//C++14出了这个等同上面
template<typename T>
std::enable_if_t<(sizeof(T) > 2),T> funceb()
{
    T myt = {};
    return myt;
}

nmsp2::funceb<int>();//int funceb(){}
//nmsp2::funceb<char>();

traits使用示例

  • 类型推断
#include <iostream>
#include <type_traits>

template<typename T>
void print_type_trait(T value) {
    // 使用std::integral_constant作为编译时的常量表达式容器
    using TraitType = std::integral_constant<bool, std::is_integral<T>::value>;
    
    // 使用if constexpr语句在编译期决定是否打印信息
    if constexpr (TraitType::value) {
        std::cout << "The type of the variable is integral: " << typeid(T).name() << '\n';
    } else {
        std::cout << "The type of the variable is not integral: " << typeid(T).name() << '\n';
    }
}

int main() {
    int integer = 10;
    double floating = 3.14;

    print_type_trait(integer); // 输出:"The type of the variable is integral"
    print_type_trait(floating); // 输出:"The type of the variable is not integral"

    return 0;
}
  • 模板函数
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type
print_sum(T a, T b) {
    std::cout << "Sum of arithmetic types: " << a + b << '\n';
}

template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value>::type
print_sum(T a, T b) {
    std::cout << "Sum operation not supported for non-arithmetic types.\n";
}

struct NonArithmetic {};

int main() {
    print_sum(3, 5); // 输出:"Sum of arithmetic types: 8"
    print_sum("Hello", "World"); // 不会被实例化,因为std::string不是算术类型
    print_sum(NonArithmetic{}, NonArithmetic{}); // 输出:"Sum operation not supported for non-arithmetic types."

    return 0;
}

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

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

相关文章

vs2019 - detected memory leak

文章目录 vs2019 - detected memory leak概述笔记vs2019 consolevs2019 MFC Dlg但是&#xff0c;工程大了之后&#xff0c;VS2019提示的就变了样整好的内存泄漏侦测头文件和实现my_debug_new_define.hmy_debug_new_define.cpp在所有.cpp文件入口处包含my_debug_new_define.h包含…

计算机系列之操作系统的系统

2、大话操作系统的启动 当按下开机键时&#xff0c;BIOS 就会开始执行 ​ BIOS 就是放在主板上 ROM 里面的一段程序。 ​ ROM Read Only Memory&#xff08;只能读取的内存&#xff09; ​ 所以 BIOS 在出厂的时候就可以直接写死在 ROM 里面。 ​ 每次开机的时候&#xff…

【数据结构与算法】之双向链表及其实现!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 目录 1、双向链表的结构及概念 2、双向链表的实现 2.1 要实现的接口…

Mac版2024 CleanMyMac X 4.15.2 核心功能详解 cleanmymac这个软件怎么样?cleanmymac到底好不好用?

近些年伴随着苹果生态的蓬勃发展&#xff0c;越来越多的用户开始尝试接触Mac电脑。然而很多人上手Mac后会发现&#xff0c;它的使用逻辑与Windows存在很多不同&#xff0c;而且随着使用时间的增加&#xff0c;一些奇奇怪怪的文件也会占据有限的磁盘空间&#xff0c;进而影响使用…

Android studio顶部‘app‘红叉- Moudle ‘XX.app’ dosen’t exist in project

Android studio顶部app红叉- Moudle ‘XX.app’ dosen’t exist in project 1、现象&#xff1a; 运行老项目或者有时候替换项目中的部分代码&#xff0c;明明没有错但是Android studio就编译报错了。 1.1 Android studio顶部app红叉。 1.2 点击Build没有clear菜单&#xff0…

软考 - 系统架构设计师 - 嵌入式真题

问题 1&#xff1a; &#xff08;1&#xff09;.HTML 静态化&#xff1a;可以实现对系统经常访问的页面进行静态化以提高系统访问的效率&#xff0c;但系统页面通常需要数据库中的用户信息和用户选择来动态显示&#xff0c;因此不适合采用。 HTML 静态化&#xff1a; 将动态生成…

windows下已经创建好了虚拟环境,但是切换不了的解决方法

用得多Ubuntu&#xff0c;今天用Windows重新更新anaconda出问题&#xff0c;重新安装之后&#xff0c;打开pycharm发现打开终端之后&#xff0c;刚开始是ps的状态&#xff0c;后面试了网上改cmd的方法&#xff0c;终端变成c盘开头了 切换到虚拟环境如下&#xff1a;目前的shell…

ON1 NoNoise AI 2024 for Mac/Win:智能降噪,重塑影像之美

在数字摄影领域&#xff0c;图片质量往往受到多种因素的影响&#xff0c;其中噪点问题尤为突出。ON1 NoNoise AI 2024作为一款专为Mac和Windows平台打造的AI图片降噪工具&#xff0c;凭借其卓越的降噪性能和智能化的操作体验&#xff0c;成为了摄影师和图像处理专家们的首选工具…

NL2SQL进阶系列(5):论文解读业界前沿方案(DIN-SQL、C3-SQL、DAIL-SQL、SQL-PaLM)、新一代数据集BIRD-SQL解读

NL2SQL进阶系列(5)&#xff1a;论文解读业界前沿方案&#xff08;DIN-SQL、C3-SQL、DAIL-SQL&#xff09;、新一代数据集BIRD-SQL解读 NL2SQL基础系列(1)&#xff1a;业界顶尖排行榜、权威测评数据集及LLM大模型&#xff08;Spider vs BIRD&#xff09;全面对比优劣分析[Text2…

基于Springboot+Vue的Java项目-免税商品优选购物商城系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

故障转移-redis

4.4.故障转移 集群初识状态是这样的&#xff1a; 其中7001、7002、7003都是master&#xff0c;我们计划让7002宕机。 4.4.1.自动故障转移 当集群中有一个master宕机会发生什么呢&#xff1f; 直接停止一个redis实例&#xff0c;例如7002&#xff1a; redis-cli -p 7002 sh…

Linux环境变量(一)

一.main参数 如果你仔细看过编程书籍就会发现&#xff0c;对于主函数main函数也是有参数的&#xff1a; 首先&#xff0c;我们先来认识两个参数&#xff1a; int main(int argc,char* argv[]) {return 0; } 对于这两个参数&#xff1a;第一个参数int类型表示为第二个的个数…

[C++][算法基础]判定二分图(染色法)

给定一个 n 个点 m 条边的无向图&#xff0c;图中可能存在重边和自环。 请你判断这个图是否是二分图。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行&#xff0c;每行包含两个整数 u 和 v&#xff0c;表示点 u 和点 v 之间存在一条边。 输出格式 如果给定图是二分图…

字体反爬知识积累2

一、os模块中函数的应用 如何获取当前文件中所有文件的路径方法 这段代码使用 os.walk()函数来遍历指定目录 imgs 下的所有子目录和文件。具体来说&#xff0c;os.walk()函数返回一个生成器&#xff0c;可以在每次迭代中获取目录树中的一个元组&#xff0c;元组包含当前目录的…

【算法】删除链表中重复元素

本题来源---《删除链表中重复元素》。 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例 2&#xff1a; 输入…

Delphi Xe 10.3 钉钉SDK开发——审批流接口(获取表单ProcessCode)

开发钉钉审批流时&#xff0c;需要用到钉钉表单的Processcode&#xff0c;有两种方法 &#xff1a; 一、手动获取&#xff1a; 管理员后台——审批——找到对应的表单&#xff1a;如图&#xff1a; ProcessCode后面就是了&#xff01; 二、接口获取&#xff1a;今天的重点&a…

Redis消息队列-基于Stream的消息队列-消费者组

7.5 Redis消息队列-基于Stream的消息队列-消费者组 消费者组&#xff08;Consumer Group&#xff09;&#xff1a;将多个消费者划分到一个组中&#xff0c;监听同一个队列。具备下列特点&#xff1a; 创建消费者组&#xff1a; key&#xff1a;队列名称 groupName&#xff1a…

SimpleImputer缺失数据处理报错解决方案

作者Toby&#xff0c;来源公众号&#xff1a;Python风控建模&#xff0c;SimpleImputer缺失数据处理报错解决方案 今天有学员反馈缺失值代码报错&#xff0c;由于sklearn缺失值处理的包升级&#xff0c;下面把官网最新的缺失值处理代码奉上。 参考https://scikit-learn.org/st…

LeetCode-热题100:101. 对称二叉树

题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a; root [1,2,2,3,4,4,3] 输出&#xff1a; true 示例 2&#xff1a; 输入&#xff1a; root [1,2,2,null,3,null,3] 输出&#xff1a; false 提示&#xff1a;…

数据库讲解---(数据更新、视图、数据控制)【MySQL版本】

目录 前言 一.数据更新 1.1插入数据 1.1.1插入单个元组 1.1.2将一个新学生记录(学号:091530,姓名:夏雨,性别:男,籍:海南,出生年份:1999,学院:计算机)插入到学生表中 1.1.3插入子查询结果 1.1.4有一个表“DEPT”(SDEPT CHAR(20),AVG_AGE SMALLINT)表示每个学院的学生的平…
最新文章