C++模板元编程(三)——类型萃取

类型萃取(type_traits)是一种编译时技术,用于在编译期间获取和操作类型的信息,主要用于泛型编程以及在编译时做出决策。


文章目录

  • 常见的类型萃取
  • 内部实现
    • std::is_integral\<T\>
    • std::enable_if_t<_Test, T>
  • 应用


常见的类型萃取

在C++11的<type_traits>头文件中,包含许多内置的类型萃取:

  1. std::is_integral<T>: 判断类型 T 是否为整型
  2. std::is_floating_point<T>: 判断类型 T 是否为浮点数类型
  3. std::is_pointer<T>: 判断类型 T 是否为指针类型
  4. std::is_reference<T>:判断类型 T 是否为引用类型
  5. std::is_const<T>:判断类型 T 是否为 const 类型
  6. std::is_same<T, U>:判断类型 TU 是否相同

这些类型萃取通常有一个静态布尔值 value,当类型符合特定条件时,它为 true 反之为 false

<xtr1common> 中也有一些内置的类型萃取:

  1. std::remove_reference_t<T> 移除类型 T 的左值引用/右值引用
  2. std::remove_cv_t<T> 移除类型 T 的常量符号
  3. std::enable_if_t<_Test, T> 如果_Test为真才有类型 T

内部实现

下面以 std::is_integral<T>std::enable_if_t<_Test, T> 为例看下它们的具体实现。

std::is_integral<T>

_EXPORT_STD template <class _Ty>
struct is_integral : bool_constant<is_integral_v<_Ty>> {};

可见其继承于 bool_constant<is_integral_v<_Ty>>,因此 typeboolvalue 是对应的布尔值
先看下 is_integral_v<_Ty>

_EXPORT_STD template <class _Ty>
_INLINE_VAR constexpr bool is_integral_v = _Is_any_of_v<remove_cv_t<_Ty>, bool, char, signed char, unsigned char,wchar_t,
#ifdef __cpp_char8_tchar8_t,
#endif // __cpp_char8_tchar16_t, char32_t, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long>;

remove_cv_t<_Ty> 移除 constvolatile 标识符

_Is_any_of_v<class _Ty, class... _Types> 如果是这些类型之一返回 true 否则返回 false,具体实现如下:

template <class _Ty, class... _Types>
_INLINE_VAR constexpr bool _Is_any_of_v = // true if and only if _Ty is in _Typesdisjunction_v<is_same<_Ty, _Types>...>;

这里的 is_same<_Ty, _Types>... 是参数包展开,创建了一系列的 is_same<T,U>
看下 is_same<T,U> 实现,其继承于 bool_constant<is_same_v<_Ty1, _Ty2>>

_EXPORT_STD template <class, class>
_INLINE_VAR constexpr bool is_same_v = false; // determine whether arguments are the same type
template <class _Ty>
_INLINE_VAR constexpr bool is_same_v<_Ty, _Ty> = true;_EXPORT_STD template <class _Ty1, class _Ty2>
struct is_same : bool_constant<is_same_v<_Ty1, _Ty2>> {};

is_same_v 可以看到当传入的是相同的类型就是 true,不同类型就是 false
bool_constant<bool _Val> 其本身是一个bool类型的整型常量,所以is_same如果类型是相等的话,就是值为 true 的一个整型常量

_EXPORT_STD template <class _Ty, _Ty _Val>
struct integral_constant {static constexpr _Ty value = _Val;using value_type = _Ty;using type       = integral_constant;constexpr operator value_type() const noexcept {return value;}_NODISCARD constexpr value_type operator()() const noexcept {return value;}
};_EXPORT_STD template <bool _Val>
using bool_constant = integral_constant<bool, _Val>;_EXPORT_STD using true_type  = bool_constant<true>;
_EXPORT_STD using false_type = bool_constant<false>;

再看下 disjunction_v<class... _Traits>

template <bool _First_value, class _First, class... _Rest>
struct _Disjunction { // handle true trait or last traitusing type = _First;
};template <class _False, class _Next, class... _Rest>
struct _Disjunction<false, _False, _Next, _Rest...> { // first trait is false, try the next traitusing type = typename _Disjunction<_Next::value, _Next, _Rest...>::type;
};_EXPORT_STD template <class... _Traits>
struct disjunction : false_type {}; // If _Traits is empty, false_typetemplate <class _First, class... _Rest>
struct disjunction<_First, _Rest...> : _Disjunction<_First::value, _First, _Rest...>::type {// the first true trait in _Traits, or the last trait if none are true
};_EXPORT_STD template <class... _Traits>
_INLINE_VAR constexpr bool disjunction_v = disjunction<_Traits...>::value;

当一个为true,就会终止展开,那么其实 disjunction_v 本身实现了一个或逻辑


std::enable_if_t<_Test, T>

它就是 enable_if<_Test, _Ty>::type

_EXPORT_STD template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;

而其通过模板偏特化来实现,如果为 true 的话就有 type 否则没有 type

_EXPORT_STD template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Testtemplate <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Testusing type = _Ty;
};

应用

比如我们想要输出容器内的元素,对于有 const_iterator 的使用 const_iterator 否则使用 iterator

#include <iostream>
#include <vector>
#include <type_traits>template <typename T>
struct has_const_iterator {
private:typedef char yes[1];typedef char no[2];template <typename C>static yes& test(typename C::const_iterator*);template <typename C>static no& test(...);
public:static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};template <typename Container>
typename std::enable_if<has_const_iterator<Container>::value>::type
print(const Container& c) {typename Container::const_iterator it;std::cout << "Using const_iterator." << std::endl;for (it = c.begin(); it != c.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;
}template <typename Container>
typename std::enable_if<!has_const_iterator<Container>::value>::type
print(const Container& c) {typename Container::iterator it;std::cout << "Using iterator." << std::endl;for (it = c.begin(); it != c.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;
}int main() {std::vector<int> v = { 1, 2, 3, 4, 5 };print(v);
}

这里 typename std::enable_if用来判断是否有 const_iterator,这是 SFINAE (Substitution Failure Is Not An Error),即模板特化失败就去掉而不是报错。

typename Container::iterator it 这是用来区分这是一个类型,而不是一个类的静态成员。

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

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

相关文章

Java请求webService,IDEA生成客户端调用代码

Axis是Apache开放源代码组织的一个项目&#xff0c;全称为Apache Extensible Interaction System&#xff0c;简称Axis。它是一个基于Java的SOAP&#xff08;Simple Object Access Protocol&#xff0c;简单对象访问协议&#xff09;引擎&#xff0c;提供创建服务器端、客户端和…

游戏开发面试题3

unity如何判断子弹射击到敌人&#xff0c;如果子弹特别快怎么办 使用物理学碰撞检测。使用Unity的物理组件&#xff0c;如Rigidbody和Collider&#xff0c;将子弹和敌人都设置为有一定的物理碰撞属性&#xff0c;当子弹碰到敌人的时候&#xff0c;就会触发OnCollisionEnter()事…

游戏开发面试题2

详细说下堆排序。 堆排序是一种选择排序算法&#xff0c;它的基本思想是&#xff1a;将待排序序列构造成一个大顶堆&#xff0c;此时&#xff0c;整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换&#xff0c;此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个…

作业训练二编程题6. 小A的计算器

【问题描述】 以往的操作系统内部的数据表示都是二进制方式&#xff0c;小A新写了一个操作系统&#xff0c;系统内部的数据表示为26进制&#xff0c;其中0-25分别由a-z表示。 现在小A要在这个操作系统上实现一个计算器&#xff0c;这个计算器要能实现26进制数的加法运算…

Ajax与Fetch API在Web开发中的性能、用法与未来趋势比较

Ajax和Fetch都是JavaScript中用于从客户端向服务器发送请求以获取数据的技术&#xff0c;但它们之间存在一些显著的区别。以下是对这两种技术的详细比较&#xff1a; 一、技术基础与实现方式 Ajax&#xff1a; 基础&#xff1a;Ajax全称为Asynchronous JavaScript and XML&…

LabVIEW的Actor Framework (AF) 结构介绍

LabVIEW的Actor Framework (AF) 是一种高级架构&#xff0c;用于开发并发、可扩展和模块化的应用程序。通过面向对象编程&#xff08;OOP&#xff09;和消息传递机制&#xff0c;AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…

ROS——多个海龟追踪一个海龟实验

目标 通过键盘控制一个海龟&#xff08;领航龟&#xff09;的移动&#xff0c;其余生成的海龟通过监听实现追踪定期获取领航龟和其余龟的坐标信息&#xff0c;通过广播告知其余龟&#xff0c;进行相应移动其余龟负责监听 疑惑点&#xff08;已解决&#xff09; int main(int…

k8s 部署RuoYi-Vue-Plus之redis搭建

1.直接部署一个pod 需要挂载存储款, 可参考 之前文章设置 https://blog.csdn.net/weimeibuqieryu/article/details/140183843 2.部署yaml 先创建命名空间ruoyi, 有就不用创建了 kubectl create namespace ruoyi创建部署文件 redis-deploy.yaml kind: PersistentVolume api…

程序员学长 | 快速学会一个算法,xLSTM

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学会一个算法&#xff0c;xLSTM 今天给大家分享一个超强的算法模型&#xff0c;xLSTM。 xLSTM&#xff08;Extended Long Short-Term Memory&…

Spring Boot的无缝衔接:深入解析与实践

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ &#x1f680;The begin&#x1f697;点点关注&#xff0c;收藏不迷路&#x1f6a9; 引言 在快速迭代的软件开发环境中&#xff0c;无缝衔接是提升开发效率、降低维护成本、增强系统稳定性的关键。Spring Boo…

Electron开发 - 如何在主进程Main中让node-fetch使用系统代理

背景 开发过程中&#xff0c;用户设置的系统代理是不同的&#xff0c;比如公司内的服务器&#xff0c;所以就要动态地使用系统代理来访问&#xff0c;但是主进程默认为控制台级别的请求&#xff0c;不走系统代理&#xff0c;除非你指定系统代理配置&#xff0c;这个就就有了这…

轻松上手MYSQL:MYSQL事务隔离级别的奇幻之旅

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索MYSQL索引数据结构之旅✨ &#x1f44b; 大家好&#xff01;文本学习…

【话题】IT专业入门,高考假期预习指南

IT专业入门&#xff0c;高考假期预习指南 亲爱的高考学子们&#xff0c; 七月的阳光&#xff0c;如同你们的梦想&#xff0c;炽热而明亮。当你们手中的笔落下最后一道题的答案&#xff0c;那不仅仅是对过去十二年寒窗苦读的告别&#xff0c;更是对未知世界探索的启程号角。你们…

ExtruOnt——为工业 4.0 系统描述制造机械类型的本体

概述 论文地址 &#xff1a;https://arxiv.org/abs/2401.11848 原文地址&#xff1a;https://ai-scholar.tech/articles/ontology/ExtruOnt 在工业 4.0 应用场景中&#xff0c;以机器可解释代码提供的、语义丰富的制造机械描述可以得到有效利用。然而&#xff0c;目前显然还缺…

无锡哲讯:SAP赋能汽车零配件行业,加速企业数字化转型

汽车零配件行业作为汽车工业的重要支撑&#xff0c;正处在一个快速变化和高度竞争的市场环境中。随着科技的不断进步和消费者需求的日益多样化&#xff0c;如何通过高效的资源管理和生产流程优化&#xff0c;提升竞争力&#xff0c;已成为汽车零配件企业亟待解决的问题。无锡哲…

玩转springboot之springboot项目监测

项目监测 springboot中提供了actuator项目来进行监测和度量 基于springboot2.x版本 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency> actuator中提…

【数智化人物展】天云数据CEO雷涛:大模型连接数据库 为数智化提供高价值数据...

雷涛 本文由天云数据CEO雷涛投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 这几天&#xff0c;奥特曼讲SQL数据库和大模型结合起来会产生什么样的化学变化引起行业关注。为…

大模型备案全网最详细流程【附附件】

本文要点&#xff1a;大模型备案最详细说明&#xff0c;大模型备案条件有哪些&#xff0c;《算法安全自评估报告》模板&#xff0c;大模型算法备案&#xff0c;大模型上线备案&#xff0c;生成式人工智能(大语言模型)安全评估要点&#xff0c;网信办大模型备案。 大模型备案安…

Geoserver源码解读五 Catalog

系列文章目录 Geoserver源码解读一 环境搭建 Geoserver源码解读二 主入口 Geoserver源码解读三 GeoServerBasePage Geoserver源码解读四 REST服务 Geoserver源码解读五 Catalog 目录 系列文章目录 前言 一、定义 二、前置知识点 1.Spring 的 Bean 生命周期 ApplicationCon…

中国石油大学(华东)24计算机考研数据速览,计科学硕复试线288分!

中国石油大学&#xff08;华东&#xff09;计算机与通信工程学院是中国石油大学(华东)十三个教学院部之一&#xff0c;其前身是创建于1984年的计算机科学系&#xff0c;2001年撤系建院。伴随着学校50多年的风雨历程&#xff0c;计算机与通信工程学院也已经有了20多年的发展历史…