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

C++中几个常用的类型选择模板函数

std::enable_if<B, T>::type

如果编译期满足B,那么返回类型T,否则编译报错

std::conditional<B, T, F>::type

如果编译期满足B,那么返回类型T,否则返回类型F

下面是一个示例,展示如何使用 `std::conditional` 来选择返回类型:

#include <iostream>
#include <type_traits>template <typename T, typename U>
auto max(T a, U b) -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U>::type {return (a > b) ? a : b;
}int main() {int a = 5;double b = 3.14;auto result = max(a, b);std::cout << "Max value: " << result << std::endl;return 0;
}

在上面的示例中,`max` 函数使用了 `std::conditional` 来根据两个参数的类型选择返回类型。如果 `sizeof(T) > sizeof(U)`,则返回类型为 `T`,否则返回类型为 `U`。在 `main` 函数中,我们调用 `max` 函数并打印返回值,演示了根据条件选择返回类型的功能。

需要注意的是,`std::conditional` 是一个模板类,它提供了在编译时进行类型选择的能力。它在很多情况下可以用来实现类型萃取(type traits)和条件编译等功能。

std::integral_constant<T, value>

`std::integral_constant<T, value>` 是 C++ 标准库中的一个模板类,用于表示一个编译时常量的包装器。它接受两个参数:`T` 表示常量的类型,`value` 表示常量的值。

`std::integral_constant<bool, B>` 表示一个固定的(常量)布尔值,其类型为 `bool`,值为 `B`。

下面是一个示例,展示如何使用 `std::integral_constant` 来表示编译时的布尔常量:```cpp
 

#include <iostream>
#include <type_traits>int main() {std::integral_constant<bool, true> true_value;std::integral_constant<bool, false> false_value;std::cout << "true_value: " << true_value << std::endl;std::cout << "false_value: " << false_value << std::endl;std::cout << "true_value type: " << typeid(true_value).name() << std::endl;std::cout << "false_value type: " << typeid(false_value).name() << std::endl;std::cout << "true_value value: " << true_value() << std::endl;std::cout << "false_value value: " << false_value() << std::endl;return 0;
}

在上面的示例中,我们创建了 `true_value` 和 `false_value` 两个 `std::integral_constant` 实例,分别表示编译时的 `true` 和 `false` 布尔常量。我们使用 `std::cout` 打印了各个常量的值、类型和调用结果。

需要注意的是,`std::integral_constant<bool, B>` 实际上是一个包装器,它提供了类型信息和调用操作符(函数调用运算符),使得它在使用时可以像一个函数一样进行调用。调用 `std::integral_constant` 对象会返回其持有的常量值。

此外,C++ 标准库中的 `std::integral_constant` 还提供了一系列的成员类型和成员函数,如 `value_type`、`operator()`、`operator bool` 等,用于操作和查询包装的常量。这些成员函数和成员类型可以用于进行类型推导、模板元编程和编译时条件判断等用途。

下面看一个比较难的应用,将类型和自定义的数字联系起来,做一些类型判断:

#include <iostream>
enum class type {none_type,// Integer types should go first,int_type,uint_type,long_long_type,ulong_long_type,int128_type,uint128_type,bool_type,char_type,last_integer_type = char_type,// followed by floating-point types.float_type,double_type,long_double_type,last_numeric_type = long_double_type,cstring_type,string_type,pointer_type,custom_type
};// Maps core type T to the corresponding type enum constant.
template <typename T>
struct type_constant : std::integral_constant<type, type::custom_type> {};#define FMT_TYPE_CONSTANT(Type, constant) \template <> \struct type_constant<Type>        \: std::integral_constant<type, type::constant> {}FMT_TYPE_CONSTANT(int, int_type);
FMT_TYPE_CONSTANT(unsigned, uint_type);
FMT_TYPE_CONSTANT(long long, long_long_type);
FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
FMT_TYPE_CONSTANT(bool, bool_type);
FMT_TYPE_CONSTANT(float, float_type);
FMT_TYPE_CONSTANT(double, double_type);
FMT_TYPE_CONSTANT(long double, long_double_type);
FMT_TYPE_CONSTANT(const void*, pointer_type);constexpr bool is_integral_type(type t) {return t > type::none_type && t <= type::last_integer_type;
}
constexpr bool is_arithmetic_type(type t) {return t > type::none_type && t <= type::last_numeric_type;
}int main()
{int a = 12;std::cout<< is_integral_type(type_constant<decltype(a)>::value)<<std::endl; //1bool* b = nullptr;std::cout<< is_integral_type(type_constant<decltype(b)>::value)<<std::endl; //0
}

std::underlying_type<T>::type

`std::underlying_type<T>::type` 是 C++ 标准库中的一个类型转换工具,它用于获取枚举类型 `T` 的底层类型。

`std::underlying_type` 是一个模板类,接受一个类型参数 `T`,它用于表示一个枚举类型。`std::underlying_type<T>::type` 表示枚举类型 `T` 的底层类型。

下面是一个示例,展示如何使用 `std::underlying_type<T>::type` 来获取枚举类型的底层类型:

#include <iostream>
#include <type_traits>enum class MyEnum : unsigned int {Value1,Value2,Value3
};int main() {using UnderlyingType = std::underlying_type<MyEnum>::type;std::cout << "Underlying type of MyEnum: " << typeid(UnderlyingType).name() << std::endl;return 0;
}

在上面的示例中,我们定义了一个枚举类型 `MyEnum`,包含三个枚举值。然后,我们使用 `std::underlying_type<MyEnum>::type` 来获取 `MyEnum` 的底层类型,并将其赋值给 `UnderlyingType` 类型别名。最后,我们使用 `std::cout` 打印底层类型的类型信息。

在这个示例中,我们使用 `std::underlying_type` 来获取 `MyEnum` 的底层类型。`UnderlyingType` 类型别名被推导为 `unsigned int`,这是 `MyEnum` 底层的类型。

`std::underlying_type` 对于在编译时获取枚举类型的底层类型非常有用。它可以用于处理枚举类型的底层值,进行位操作或其他需要底层类型的操作。

std::remove_cv<remove_reference_t<T>>::type

移除类型T的各种限定符。

比如:const、volatile、左值引用T&。

std::is_same<T, T2>::value

std::is_same<T, T2>::value 是 C++ 标准库中的一个类型特性工具,用于检查类型 T 和类型 T2 是否相同。值得注意的是,cv限定符会让类型不同。

#include <iostream>
#include <type_traits>int main() {bool isSame = std::is_same<int, int>::value;std::cout << "isSame: " << isSame << std::endl; // trueisSame = std::is_same<int, double>::value;std::cout << "isSame: " << isSame << std::endl; // falsebool isSame = std::is_same<const int, int>::value;std::cout << "isSame: " << isSame << std::endl; // falseisSame = std::is_same<volatile int, int>::value;std::cout << "isSame: " << isSame << std::endl; // falseisSame = std::is_same<const int, volatile int>::value;std::cout << "isSame: " << isSame << std::endl; // falsereturn 0;
}

std::is_base_of<T, D>::value

`std::is_base_of<compile_string, S>` 是 C++ 标准库中的一个模板类 `std::is_base_of` 的使用,用于检查类型 `S` 是否是类型 `compile_string` 的基类或派生类。

`std::is_base_of` 是一个类型特性(type trait),它提供了一种在编译时判断一个类型是否是另一个类型的基类或派生类的机制。它属于 C++ 类型特性库(type traits library)的一部分,位于 `<type_traits>` 头文件中。

在给定的代码中,`std::is_base_of<compile_string, S>` 用于检查类型 `S` 是否是类型 `compile_string` 的基类或派生类。它返回一个编译时常量值 `true` 或 `false`,表示 `S` 是否是 `compile_string` 的派生类。

具体的使用示例如下:

// A base class for compile-time strings.
struct compile_string {};template <typename S>
struct is_compile_string : std::is_base_of<compile_string, S> {};template <typename S, std::enable_if<is_compile_string<S>::value>::value>
constexpr auto to_string_view(const S& s)-> basic_string_view<typename S::char_type> {return basic_string_view<typename S::char_type>(s);
}

在上面的示例中,我们使用 `std::is_base_of` 来检查 `derived_class` 是否是 `compile_string` 的派生类。根据返回的结果,我们输出相应的信息。

需要注意的是,`std::is_base_of` 是在编译时进行类型检查的,它只能用于判断类型之间的继承关系,而不能用于检查对象之间的关系。

std::declval<T>()

std::declval<S> 是 C++ 标准库中的一个模板函数 std::declval 的使用,用于获取类型 S 的一个虚拟值(引用)。

std::declval 是一个函数模板,它允许在不实际创建对象的情况下,获取一个类型的虚拟值。它位于 <utility> 头文件中。

在给定的代码中,std::declval<S> 用于获取类型 S 的一个虚拟值。它返回一个该类型的右值引用(Rvalue reference)。

std::declval 的主要用途是用于在编译时创建对类型的引用,以便在模板编程中进行类型推断。它通常与 decltype 一起使用,用于声明返回类型或推断表达式的类型。需要注意的是,std::declval 用于创建虚拟值,但不能用于实际访问该值。它主要用于模板元编程中,用于推断类型和进行 SFINAE(Substitution Failure Is Not An Error)。

template <typename S>
struct is_string: std::is_class<decltype(detail::to_string_view(std::declval<S>()))> {};template <typename S, typename = void> struct char_t_impl {};
template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {using result = decltype(to_string_view(std::declval<S>()));using type = typename result::value_type;
};// detail::to_string_view see belowtemplate <typename Char, std::enable_if<is_char<Char>::value)>::value>
inline auto to_string_view(const Char* s) -> basic_string_view<Char> {return s;
}
template <typename Char, typename Traits, typename Alloc>
inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s)-> basic_string_view<Char> {return s;
}
template <typename Char>
constexpr auto to_string_view(basic_string_view<Char> s)-> basic_string_view<Char> {return s;
}
template <typename Char,std::enable_if<!std::is_empty<std_string_view<Char>>::value>::value>
inline auto to_string_view(std_string_view<Char> s) -> basic_string_view<Char> {return s;
}
template <typename S, std::enable_if<is_compile_string<S>::value>::value>
constexpr auto to_string_view(const S& s)-> basic_string_view<typename S::char_type> {return basic_string_view<typename S::char_type>(s);
}
void to_string_view(...);

比如上面,创建了一个虚拟的S对象的引用,用于驱动`detail::to_string_view`模板进行类型推断,从而判断是否可以继续编译。

相关文章:

C++中几个常用的类型选择模板函数

std::enable_if<B, T>::type 如果编译期满足B&#xff0c;那么返回类型T&#xff0c;否则编译报错 std::conditional<B, T, F>::type 如果编译期满足B&#xff0c;那么返回类型T&#xff0c;否则返回类型F 下面是一个示例&#xff0c;展示如何使用 std::condit…...

【LeetCode】1321. 餐馆营业额变化增长

表: Customer ------------------------ | Column Name | Type | ------------------------ | customer_id | int | | name | varchar | | visited_on | date | | amount | int | ------------------------ 在 SQL 中&#xff0c;(custo…...

【网络技术】【Kali Linux】Wireshark嗅探(八)动态主机配置协议(DHCP)

一、实验目的 本次实验使用 Wireshark &#xff08;“网鲨”&#xff09;流量分析工具进行网络流量嗅探&#xff0c;旨在初步了解动态主机配置协议&#xff08;DHCP协议&#xff09;的工作原理。 二、DHCP协议概述 动态主机配置协议&#xff08; D ynamic H ost C onfigurat…...

算法29:不同路径问题(力扣62和63题)--针对算法28进行扩展

题目&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff0…...

openGauss学习笔记-188 openGauss 数据库运维-常见故障定位案例-core问题定位

文章目录 openGauss学习笔记-188 openGauss 数据库运维-常见故障定位案例-core问题定位188.1 磁盘满故障引起的core问题188.1.1 问题现象188.1.2 原因分析188.1.3 处理办法 188.2 GUC参数log_directory设置不正确引起的core问题188.2.1 问题现象188.2.2 原因分析188.2.3 处理办…...

kubernetes入门到进阶(5)

目录 镜像仓库&#xff1a;怎么用好docker hub这个宝藏 什么是镜像仓库&#xff08;Registry&#xff09; 什么是docker hub 如何在docker hub上挑选镜像 docker hub上进行概念股命名规则是什么 该怎么上传自己的镜像 离线环境该怎么办 小结 镜像仓库&#xff1a;怎么用好docke…...

【字典树Trie】LeetCode-139. 单词拆分

139. 单词拆分。 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xff1a; 输入: s "leetcode&q…...

pytest常用的第三方插件介绍

本节介绍了如何安装和使用第三方插件。如果你想要编写自己的插件&#xff0c;请参阅“编写插件”。 通过pip可以轻松安装第三方插件&#xff1a; pip install pytest-NAME pip uninstall pytest-NAME如果已经安装了插件&#xff0c;pytest会自动找到并集成它&#xff0c;无需手…...

【经验】VSCode连接远程服务器(可以使用git管理、方便查看和编辑Linux源码)

1、查看OpenSSH Windows10通常自带OpenSSH不需要安装。 Windows10下检查是否已经安装OpenSSH的方法: 1)按下快捷键Win + X,选择Windows PoweShell(管理员) 2)输入以下指令: Get-WindowsCapability -Online | ? Name -like ‘OpenSSH*’ 3)如果电脑未安装OpenSSH,…...

机器学习-生存分析:如何基于随机生存森林训练乳腺癌风险评估模型?

一、 引言 乳腺癌是女性最常见的恶性肿瘤之一&#xff0c;也是全球范围内女性死亡率最高的癌症之一。据统计&#xff0c;每年全球有超过200万人被诊断为乳腺癌&#xff0c;其中约60万人死于该疾病。因此&#xff0c;乳腺癌的早期诊断和风险评估对于预防和治疗乳腺癌具有非常重要…...

MySQL学习笔记1: 数据库的简单介绍

目录 1. 数据库是什么2. 数据库这一类软件中的一些典型代表2.1. Oracle2.2. MySQL2.3. SQL Server2.4. SQLite (lite 轻量版) 3. 数据库的类型3.1. 关系型数据库3.2. 非关系型数据库 4. 总结 1. 数据库是什么 数据库是一类软件&#xff0c;这一类软件可以用来管理数据&#xf…...

【Docker】安装ELK(Docker Compose)

一、创建挂载目录 mkdir -p /docker/elk/elasticsearch/{plugins,data} mkdir -p /docker/elk/logstash 二、给目录授权 chmod 777 /docker/elk/elasticsearch/data 创建logstash配置文件 vim /docker/elk/logstash/logstash.conf input {tcp {mode => "server" h…...

【机器学习:欧氏距离 】机器学习中欧氏距离的理解和应用

【机器学习&#xff1a;欧氏距离 】机器学习中欧氏距离的理解和应用 距离公式二维更高的维度点以外的物体属性欧几里得距离的平方概括历史 在数学中&#xff0c;欧氏距离’是指欧氏空间中任意两点之间的直线距离。这种距离可以通过应用勾股定理来计算&#xff0c;利用两点的笛卡…...

系统安全及应用

1、基本安全措施 1.1、系统账号清理 在Linux系统中&#xff0c;除了用户手动创建的各种账号之外&#xff0c;还包括随系统或程序安装过程而生产的其他大量账号。除了超级用户root之外&#xff0c;其他大量账号只是用来维护系统运作、启动或保持服务进程&#xff0c;一般是不允…...

Danil Pristupov Fork(强大而易用的Git客户端) for Mac/Windows

在当今软件开发领域&#xff0c;团队协作和版本控制是非常重要的方面。在这个过程中&#xff0c;Git成为了最受欢迎的版本控制工具之一。然而&#xff0c;对于Git的使用&#xff0c;一个好的客户端是至关重要的。 今天&#xff0c;我们要为大家介绍一款强大而易用的Git客户端—…...

最新GPT4.0使用教程,AI绘画,ChatFile文档对话总结+GPT语音对话使用,DALL-E3文生图

一、前言 ChatGPT3.5、GPT4.0、GPT语音对话、Midjourney绘画&#xff0c;文档对话总结DALL-E3文生图&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和…...

【ARM 嵌入式 编译系列 7.2 -- GCC 链接脚本中 DEFINED 函数与 “AT>“ 符号详细介绍】

文章目录 GCC 链接脚本中 DEFINED 函数DEFINED() 函数> (放置在哪个区域)AT> (加载地址) (填充字节) 在链接脚本中&#xff0c;组合示例 GCC 链接脚本中 DEFINED 函数 在 ARM GCC 链接脚本&#xff08;.ld 文件&#xff09;中&#xff0c;DEFINED() 是一种内置函数&…...

Linux基础——进程初识(二)

1. 对当前目录创建文件的理解 我们知道在创建一个文件时&#xff0c;它会被默认创建到当前目录下&#xff0c;那么它是如何知道当前目录的呢&#xff1f; 对于下面这样一段代码 #include <stdio.h> #include <unistd.h>int main() {fopen("tmp.txt", …...

国科大图像处理2024速通期末——汇总2017-2019、2023回忆

国科大2023.12.28图像处理0854期末重点 图像处理 王伟强 作业 课件 资料 一、填空 一个阴极射线管它的输入与输出满足 s r 2 sr^{2} sr2&#xff0c;这将使得显示系统产生比希望的效果更暗的图像&#xff0c;此时伽马校正通常在信号进入显示器前被进行预处理&#xff0c;令p…...

编程笔记 html5cssjs 026 HTML输入类型(2/2)

编程笔记 html5&css&js 026 HTML输入类型&#xff08;2/2&#xff09; 输入类型&#xff1a;date输入类型&#xff1a;color输入类型&#xff1a;range输入类型&#xff1a;month输入类型&#xff1a;week输入类型&#xff1a;time输入类型&#xff1a;datetime输入类型…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...