当前位置: 首页 > news >正文

学习模板元编程(2)std::true_type/false_type

目录

实现原理

应用场景

条件编译

通过特化和继承,实现std::is_xxx系列

思路

举例

例子1,is_bool

例子2,is_ptr


实现原理

std::true_type/false_type是模板intergral_constant的两种实现:

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

应用场景

条件编译

先看一个不使用true_type/false_type,结果编译失败的例子。

编程者的用意是通过一个布尔型变量,配合一个模板类型参数T,控制类的行为:

#include <iostream>template<class T, bool b>
class fail
{
public:T a;fail(){if (b){a = 10;std::cout << a << std::endl;}else{a = "10";std::cout << a << std::endl;}}
};
int main(void)
{fail<int, true> f;std::cin.get();return 0;
}

编译失败:

诚然,a="10"这个分支是不会在运行时命中的,但是这个分支仍会在编译时被编译。而a是个整型(因为fail<int, true>) ,所以给整型赋值字符串将导致编译失败。

从上面的分析可以看出,运行时仍然保留了两个条件分支,是编译失败的原因。

现在使用std::true_type/false_type,让编译时就命中条件分支,并进行有选择的编译,避免语法错误

#include <iostream>
//注:这里使用vs2013,而bool_constant是C++17标准引入的,所以这里手动定义
template<bool val>
using bool_constant = std::integral_constant<bool, val>;template<class T, bool b>
class fail
{
public:T a;fail(){
//注:这里一定要有(),
//否则func函数的输入参数就是一个类型bool_constant<b>,而不是一个变量
//而类型不能作为输入参数func(bool_constant<b>());}void func (std::true_type t){a = 10;std::cout << a << std::endl;}void func(std::false_type f){a = "10";std::cout << a << std::endl;}
};
int main(void)
{fail<int, true> f;std::cin.get();return 0;
}

编译通过,且正常运行:

这里采用的是模板匹配的办法,没有直接用true/false命中条件分支,而是先通过true/false实现bool_constant的具体类型(true_type/false_type)。利用类型的区别来匹配合适的func()。

具体实现时,要注意两点:

1 要用func(bool_constant<b>()),而不是func(bool_constant<b>),因为bool_constant<b>只是个类型,不是变量,不能作为输入参数;

2 两个func()函数定义的时候(func(std::true_type), func(std::false_type)),里面还指明了具体的变量名(t,f)。其实也可以不指明变量名,因为这两个变量在函数体内没有用到,也不会因为没有变量名就影响匹配。

通过特化和继承,实现std::is_xxx系列

思路

先假定被判断的类型“不是”定义一个模板,既然不是,就继承false_type,然后再特化之,定义“是”的情况,既然是,就继承true_type。

举例

例子1,is_bool
#include <iostream>template<class T>
struct is_bool : std::false_type
{};template<>
struct is_bool<bool> : std::true_type
{};int main(void)
{std::cout << is_bool<int>() << std::endl;std::cout << is_bool<bool>() << std::endl;std::cin.get();return 0;
}

结果:

 至于为什么cout可以直接输出is_bool<int/bool>(),它又不是一个简单的布尔型,而是一个自定义的结构体?那是因为类型转换函数的结果,参见类型转换运算符(conversion operator)-CSDN博客

例子2,is_ptr

代码:

#include <iostream>template<class T>
struct is_ptr : std::false_type
{};template<class T>
struct is_ptr<T *> : std::true_type
{};int main(void)
{std::cout << is_ptr<int>() << std::endl;std::cout << is_ptr<int *>() << std::endl;std::cin.get();return 0;
}

结果:

关于模板如何匹配到指针,那是因为模板匹配的原则是匹配与当前情况最贴切的模板。参看我前面的博客初尝类型萃取--typename、模板偏特化、和traits之(二)模板偏特化-CSDN博客

http://www.dtcms.com/a/311339.html

相关文章:

  • 垃圾收集器ParNewCMS与底层三色标记算法详解
  • Redisson高并发实战:Netty IO线程免遭阻塞的守护指南
  • JVM 03 类加载机制
  • uniapp scroll-view解析
  • 常用git命令
  • 算法训练营DAY46 第九章 动态规划part13
  • 【龙芯99派新世界】buildroot快速使用笔记
  • SPI通信中CS片选的两种实现方案:硬件片选与软件片选
  • 电力系统分析学习笔记(二)- 标幺值计算与变压器建模
  • QT5.12.8 QTabWidget 透明样式QSS
  • Flask + YARA-Python*实现文件扫描功能
  • C++音视频开发:基础面试题
  • STM32 GPIO 中8种配置模式
  • 图漾AGV行业常用相机使用文档
  • 快速了解机器学习
  • 【机器学习】非线性分类算法详解(下):决策树(最佳分裂特征选择的艺术)与支持向量机(最大间隔和核技巧)
  • Python Pandas.unique函数解析与实战教程
  • mac中使用gvm install没有效果
  • 【Android】进度条ProgressBar 可拖拽进度条Seekbar
  • 云运维解决方案(word)
  • Python 入门指南:从零基础到环境搭建
  • 数字化转型-灯塔工厂建设
  • StyleX:Meta推出的高性能零运行时CSS-in-JS解决方案
  • 数字图像处理(冈萨雷斯)第三版:第一章绪论主要内容和重点——(数字图像处理的一些概念)
  • C语言数据结构(4)单链表专题2.单链表的应用
  • 什么是需量跟随
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现道路上头盔的检测识别(C#代码,UI界面版)
  • Linux 嵌入式开发全流程
  • C语言(长期更新)第7讲:VS实用调试技巧
  • LVGL + ESP-Brookesia 在Windows下的编译和运行