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`模板进行类型推断,从而判断是否可以继续编译。

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

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

相关文章

C++上位软件通过Snap7开源库访问西门子S7-1200/S7-1500数据块的方法

前言 本人一直从事C上位软件开发工作较多&#xff0c;在之前的项目中通过C访问西门子PLC S7-200/S7-1200/S7-1500并进行数据交互的应用中一直使用的是ModbusTCP/ModbusRTU协议进行。Modbus上位开源库采用的LibModbus。经过实际应用发现Modbus开源库单次发送和接受的数据不能超过…

实现一个网页聊天室

HTML代码&#xff1a; <!DOCTYPE html> <html> <head> <title>网页聊天室</title> </head> <body> <div id"chatBox" style"width: 500px; height: 300px; border: 1px solid black;"> <d…

怎么制作一款简单的小游戏?

想要制作开发一款简单的小游戏,你需要知道以下这些流程&#xff1a; 1. 规划游戏概念 游戏类型: 决定游戏类型&#xff08;如解谜、平台跳跃、射击等&#xff09;。 故事和目标: 简要概述游戏的主题、故事背景和玩家要达成的目标。 2. 设计游戏玩法 规则和机制: 设定游戏规…

手把手带你手撕一个shell

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;HEART BEAT—YOASOBI 2:20━━━━━━️&#x1f49f;──────── 5:35 &#x1f504; ◀️ ⏸ ▶️ ☰ …

解决Android Studio The path ‘X:\XXX‘ does not belong to a directory.

目录 前言 一、问题描述 二、解决方法 前言 在移动应用开发领域&#xff0c;Android Studio作为一款功能强大的集成开发环境&#xff0c;为开发人员提供了丰富的工具和功能。然而&#xff0c;在使用Android Studio的过程中&#xff0c;有时也会遇到各种各样的问题和错误。 &…

[Redis] Redisson实现分布式锁

实现分布式锁的方式有多种&#xff0c;例如基于数据库、Redis、ZooKeeper 等中间件来实现&#xff0c;它们通常依赖于这些中间件提供的事务特性&#xff0c;或者命令语义来达到分布式环境下的锁效果。例如&#xff0c;Redis 通过 SETNX 命令配合过期时间可实现一个简单的分布式…

0基础学习VR全景平台篇第134篇:720VR全景,云台调整节点

相机、云台和脚架全套设备组装完成后需要进行调校才能开始拍摄。这一节&#xff0c;我们将主要介绍云台调整的两个内容&#xff1a;对中心靶、调三点一线。&#xff08;后附调校原理&#xff09; 云台部件名称 一、调节准备 &#xff08;一&#xff09;对于安装好的云台 1.检…

clickhouse-client INSERT CSV/TSV时跳过错误行

clickhouse-client INSERT CSV/TSV时跳过错误行 在使用clickhouse-client向ck中导入csv文件时&#xff0c;当csv中有个别行数据格式错误时&#xff0c;整个文件就插入失败了&#xff0c;经常会导致丢数据。 经过一番搜索&#xff0c;发现ck提供了两个参数可以跳过错误行&#x…

三、C语言分支与循环知识点补充——随机数生成

本章分支结构的学习内容如下&#xff1a; 三、C语言中的分支与循环—if语句 (1) 三、C语言中的分支与循环—关系操作符 (2) 三、C语言中的分支与循环—条件操作符 与逻辑操作符(3) 三、C语言中的分支与循环—switch语句&#xff08;4&#xff09;分支结构 完 本章循环结构的…

java实验室预约管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 实验室预约管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean&#xff08;mvc模式)&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数 据库&#xff0c;系统主要采用B/S模式开发。开发环境为T…

【触想智能】嵌入式工控一体机的特点与应用场景分析

嵌入式工控一体机是一种用于工业自动化控制的计算机设备&#xff0c;它将显示器、主机、键盘、鼠标等器件集成在一起&#xff0c;具有高可靠性、抗干扰能力强、易于维护等特点。 嵌入式工控一体机&#xff0c;有内嵌式和外嵌式两种&#xff0c;在社会生产中被广泛应用&#xff…

【194】PostgreSQL 14.5 编写SQL从身份证号中查找性别,并且更新性别字段。

假设有一张用户表 t_user &#xff0c;该表设计如下&#xff1a; id: character varying 主键 name: character varying 姓名 idcard: character varying 身份证号 gender: smallint 性别&#xff0c;女是0&#xff0c;男是1根据身份证号查找所有未填写…

stable diffusion 基础教程-文生图

置顶大模型插件资源链接 你如果没有魔法上网,请自取 百度云盘链接:链接:https://pan.baidu.com/s/1_xAu47XMdDNlA86ufXqAuQ?pwd=23wi 提取码:23wi 有疑问加微:mincarver 界面介绍 参数解释 参数解释Sampling method扩散去噪算法的采样模式,不同采样模式会带来不一样的效…

thinkadmin小程序用户登录,获取手机号

<?php namespace app\api\controller; use app\data\service\UserAdminService; use app\data\service\UserTokenService; use think\facade\D

C++_菱形继承(虚继承)

菱形继承 and 虚继承 菱形继承介绍菱形继承源码菱形继承运行结果 虚继承介绍虚继承源码虚继承运行结果 菱形继承介绍 本文主要介绍菱形继承基本操作(仅附源码 and 运行结果) 1.正常菱形继承 会产生 在孙子类 中产生两个 不同的基类 菱形继承逻辑图 菱形继承源码 #include<…

某金属加工公司的核心人才激励体系搭建项目纪实

【客户行业】金属加工行业 【问题类型】薪酬体系/激励体系 【客户背景】 某大型金属加工企业位于河北地区&#xff0c;成立于2000年&#xff0c;隶属于某大型有色金属集团&#xff0c;是一家集科研、开发、生产、销售于一体的国有企业&#xff0c;人员达到1000人。经过多年…

Linux内核--进程管理(九)Linux内核进程管理进程优先级

目录 一、引言 二、NICE值(静态优先级) 三、优先级和实时进程 ------>3.1、chrt ------>3.2、实时/非实时进程的区 四、O1调度 ------>4.1、多核平均负载指数 ------>4.2、O1调度器处理流程 五、CFS完全公平调度 ------>5.1、产生调度的时机 ------&…

微信小程序使用mqtt开发可以,真机不行

以下可以解决我的问题&#xff0c;请一步一步跟着做&#xff0c;有可能版本不一样就失败了 一、下载mqtt.js 前往蓝奏云 https://wwue.lanzouo.com/iQPdc1k50hpe 下载好后将.txt改为.js 然后放入项目里 二、连接mqtt const mqtt require(../../utils/mqtt.min); let cli…

关于“Python”的核心知识点整理大全64

目录 20.2.15 确保项目的安全 settings.py 20.2.16 提交并推送修改 20.2.17 创建自定义错误页面 1. 创建自定义模板 500.html settings.py settings.py 注意 views.py 20.2.18 继续开发 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xff1a…

LiveGBS流媒体平台GB/T28181常见问题-国标编号是什么设备编号和通道国标编号标记唯一的摄像头|视频|镜头通道

LiveGBS国标GB28181中国标编号是什么设备编号和通道国标编号标记唯一的摄像头|视频|镜头通道 1、什么是国标编号&#xff1f;2、国标设备ID和通道ID3、ID 统一编码规则4、搭建GB28181视频直播平台 1、什么是国标编号&#xff1f; 国标GB28181对接过程中&#xff0c;可能有的小…