突破编程_C++_C++11新特性(type_traits的复合类型特性以及关系类型特性)

1 type_traits 复合类型特性

1.1 std::is_function

std::is_function 是一个模板类,用于检查一个类型是否为函数类型。

定义:

template< class T >  
struct is_function;

当 T 为函数类型则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  int myFunction() { return 0; }  int main() {  std::cout << std::boolalpha;  std::cout << "myFunction is " << std::is_function<decltype(myFunction)>::value << '\n'; // 输出 true  std::cout << "int is " << std::is_function<int>::value << '\n'; // 输出 false  return 0;  
}

1.2 std::is_class

std::is_class 是一个模板类,用于检查一个类型是否为类类型(不包括联合体)。

定义:

template< class T >  
struct is_class;

当 T 为类类型(不包括联合体)则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  struct MyClass {};  
union MyUnion {};  int main() {  std::cout << std::boolalpha;  std::cout << "MyClass is " << std::is_class<MyClass>::value << '\n'; // 输出 true  std::cout << "MyUnion is " << std::is_class<MyUnion>::value << '\n'; // 输出 false  std::cout << "int is " << std::is_class<int>::value << '\n'; // 输出 false  return 0;  
}

1.3 std::is_union

std::is_union 是一个模板类,用于检查一个类型是否为联合体(union)类型。

定义:

template< class T >  
struct is_union;

当 T 为联合体类型则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  struct MyClass {};  
union MyUnion {};  int main() {  std::cout << std::boolalpha;  std::cout << "MyClass is " << std::is_union<MyClass>::value << '\n'; // 输出 false  std::cout << "MyUnion is " << std::is_union<MyUnion>::value << '\n'; // 输出 true  std::cout << "int is " << std::is_union<int>::value << '\n'; // 输出 false  return 0;  
}

1.4 std::is_enum

std::is_enum 是一个模板类,用于检查一个类型是否为枚举类型。

定义:

template< class T >  
struct is_enum;

当 T 为枚举类型则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  enum MyEnum { ENUM_VALUE };  int main() {  std::cout << std::boolalpha;  std::cout << "MyEnum is " << std::is_enum<MyEnum>::value << '\n'; // 输出 true  std::cout << "int is " << std::is_enum<int>::value << '\n'; // 输出 false  return 0;  
}

1.5 std::is_member_function_pointer

std::is_member_function_pointer 是一个模板类,用于检查一个类型是否为成员函数指针类型。

定义:

template< class T >  
struct is_member_function_pointer;

当 T 为为成员函数指针类型则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  struct MyClass {  void myMemberFunction() {}  
};  int main() {  std::cout << std::boolalpha;  std::cout << "Pointer to member function is "  << std::is_member_function_pointer<void (MyClass::*)()>::value << '\n'; // 输出 true  std::cout << "Pointer to data member is "  << std::is_member_function_pointer<int (MyClass::*)>::value << '\n'; // 输出 false  std::cout << "int is " << std::is_member_function_pointer<int>::value << '\n'; // 输出 false  return 0;  
}

1.6 std::is_member_object_pointer

std::is_member_object_pointer 是一个模板类,用于检查一个类型是否为成员对象指针类型。

定义:

template< class T >  
struct is_member_object_pointer;

当 T 为成员对象指针类型则为 true,否则为 false。

样例:

#include <iostream>  
#include <type_traits>  struct MyClass {  int myMemberVariable;  
};  int main() {  std::cout << std::boolalpha;  std::cout << "Pointer to member object is "  << std::is_member_object_pointer<int (MyClass::*)>::value << '\n'; // 输出 true  std::cout << "Pointer to member function is "  << std::is_member_object_pointer<void (MyClass::*)()>::value << '\n'; // 输出 false  std::cout << "int is " << std::is_member_object_pointer<int>::value << '\n'; // 输出 false  return 0;  
}

2 type_traits 复合类型特性在模板元编程中的应用

以下是一个综合示例,它展示了如何在模板类和模板函数中根据类型是否为函数或类来定制行为。

#include <iostream>  
#include <type_traits>  // 模板类,根据类型T是否为类来提供不同的成员  
template<typename T>
class MyClass {
public:void doSomething() {if (std::is_class<T>::value) {std::cout << "T is a class type." << std::endl;// 执行针对类类型的操作  }else {std::cout << "T is not a class type." << std::endl;// 执行针对非类类型的操作  }}
};// 模板函数,根据类型T是否为函数来执行不同的逻辑  
template<typename T>
typename std::enable_if<!std::is_function<T>::value>::type
handleType() {std::cout << "The type is not a function type." << std::endl;// 执行针对非函数类型的操作  
}template<typename T>
typename std::enable_if<std::is_function<T>::value>::type
handleType() {std::cout << "The type is a function type." << std::endl;// 执行针对函数类型的操作  
}// 一个示例函数类型  
void exampleFunction() {}int main() 
{// 使用MyClass模板类,测试int类型和自定义结构体类型  MyClass<int> intInstance;intInstance.doSomething(); // 输出: T is not a class type.  struct MyStructType {// 自定义结构体  };MyClass<MyStructType> structInstance;structInstance.doSomething(); // 输出: T is a class type.  // 使用handleType模板函数,测试函数类型和int类型  handleType<decltype(exampleFunction)>(); // 输出: The type is a function type.  handleType<int>(); // 输出: The type is not a function type.  return 0;
}

上面代码的输出为:

T is not a class type.
T is a class type.
The type is a function type.
The type is not a function type.

在这个示例中,MyClass 模板类根据 T 是否为类类型来定制其 doSomething 方法的行为。如果 T 是类类型,它将输出相应的信息;否则,它将输出另一个信息。

handleType 模板函数使用了函数重载和 std::enable_if 来根据类型是否为函数类型来提供两个不同的模板函数实现。这是 SFINAE(Substitution Failure Is Not An Error)技术的一个应用,它允许编译器在模板解析阶段基于某个条件启用或禁用特定的函数模板。

3 type_traits 关系类型特性

3.1 std::is_base_of

std::is_base_of 是一个模板,用于检查一个类型是否是另一个类型的基类。

定义:

template<typename Base, typename Derived>  
struct is_base_of;

这里 Base 表示基类,Derived 表示派生类。is_base_of 模板返回一个布尔类型的 std::integral_constant 实例,如果 Derived 公有继承自 Base,则返回 std::true_type,否则返回 std::false_type。

样例:

#include <iostream>  
#include <type_traits>  class Base { };  
class Derived : public Base { };  int main() {  // 检查 Derived 是否是 Base 的基类(应该返回 false)  bool is_base = std::is_base_of<Derived, Base>::value;  std::cout << std::boolalpha << "Is Derived a base of Base? " << is_base << std::endl; // 输出 false  // 检查 Base 是否是 Derived 的基类(应该返回 true)  bool is_derived = std::is_base_of<Base, Derived>::value;  std::cout << "Is Base a base of Derived? " << is_derived << std::endl; // 输出 true  return 0;  
}

3.2 std::is_convertible

std::is_convertible 是一个模板,用于检查一个类型是否可以隐式转换为另一个类型。

定义:

template<typename From, typename To>  
struct is_convertible;

这里 From 表示要转换的源类型,To 表示目标类型。is_convertible 模板返回一个布尔类型的 std::integral_constant 实例,如果 From 类型可以隐式转换为 To 类型,则返回 std::true_type,否则返回 std::false_type。

样例:

#include <iostream>  
#include <type_traits>  int main() {  // 检查 int 是否可以转换为 double(应该返回 true)  bool is_convertible = std::is_convertible<int, double>::value;  std::cout << std::boolalpha << "Is int convertible to double? " << is_convertible << std::endl; // 输出 true  // 检查 const char* 是否可以转换为 std::string(应该返回 true,因为 const char* 可以隐式转换为 std::string)  bool is_string_convertible = std::is_convertible<const char*, std::string>::value;  std::cout << "Is const char* convertible to std::string? " << is_string_convertible << std::endl; // 输出 true  // 检查 std::string 是否可以转换为 int(应该返回 false)  bool is_int_convertible = std::is_convertible<std::string, int>::value;  std::cout << "Is std::string convertible to int? " << is_int_convertible << std::endl; // 输出 false  return 0;  
}

4 type_traits 关系类型特性在工厂模式中的应用

下面是一个使用 std::is_base_of 应用于工厂模式的示例。这个示例将创建一个工厂类,它根据传入的类型参数创建不同的对象。然后使用 std::is_base_of 来确保请求创建的对象类型是从某个基类继承的。

首先,定义一个基类和一些派生类:

#include <iostream>  
#include <string>  
#include <type_traits>  
#include <map>  
#include <memory>  class Base {  
public:  virtual ~Base() {}  virtual void print() const = 0;  
};  class DerivedA : public Base {  
public:  void print() const override { std::cout << "DerivedA\n"; }  
};  class DerivedB : public Base {  
public:  void print() const override { std::cout << "DerivedB\n"; }  
};

接下来,实现一个工厂类,它使用 std::is_base_of 来确保请求的类型是从Base类继承的:

class Factory {
public:template<typename T>static void registerType(const std::string& name) {creators[name] = &createT<T>;}template<typename T>static std::enable_if_t<std::is_base_of<Base, T>::value, std::unique_ptr<Base>> create(const std::string& name) {auto it = creators.find(name);if (it != creators.end()) {return std::unique_ptr<Base>(it->second());}throw std::invalid_argument("Unknown type name");}template<typename T>static std::enable_if_t<!std::is_base_of<Base, T>::value, std::unique_ptr<Base>> create(const std::string& name) = delete;private:template<typename T>static Base* createT() {return new T();}private:static std::map<std::string, Base*(*)()> creators;};std::map<std::string, Base*(*)()> Factory::creators;template<typename T>
void registerType() {static_assert(std::is_base_of<Base, T>::value, "Type must be derived from Base");Factory::registerType<T>(typeid(T).name());
}

注意,这里使用 std::enable_if_t 和 SFINAE 来在编译时启用或禁用工厂类的 create 方法。同时也使用了一个静态断言来确保在注册类型时,类型是从 Base 类继承的。

现在,可以注册类型并使用工厂来创建对象:

int main() 
{// 注册类型  registerType<DerivedA>();registerType<DerivedB>();// 通过字符串创建对象  try {auto objA = Factory::create<Base>("class DerivedA"); // 注意:这里使用了typeid(DerivedA).name()的结果,实际使用中应使用更稳定的类型名称映射  objA->print(); // 输出: DerivedA  auto objB = Factory::create<Base>("class DerivedB"); // 注意:这里使用了typeid(DerivedB).name()的结果,实际使用中应使用更稳定的类型名称映射  objB->print(); // 输出: DerivedB  }catch (const std::exception& e) {std::cerr << "Exception: " << e.what() << std::endl;}return 0;
}

上面代码的输出为:

DerivedA
DerivedB

注意,上面的示例中使用了 typeid(T).name() 来获取类型的名称,这通常不是一个好的实践,因为 name() 返回的字符串格式是依赖于实现的,并且在不同的编译器或平台之间可能不同。在实际应用中,应该使用一种更稳定的方式来映射类型名称,比如使用枚举、字符串常量或者专门的类型注册机制。

此外,在这个例子中并没有用到 std::is_convertible ,因为这里的工厂是通过类型名称直接映射到创建函数的,而不是通过类型之间的转换。如果需要基于某种形式的类型标识(如字符串或整数)来间接地创建对象,并且这个标识可以转换为具体的类型,那么 std::is_convertible 可以用来检查这种转换是否合法。

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

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

相关文章

专业前沿问题问答合集10-2——比特币的加密原理

专业前沿问题问答合集10-2——比特币的加密原理 比特币的加密原理 比特币作为一种加密货币,其安全性和功能性主要基于密码学原理和区块链技术。以下是比特币加密原理的关键组成部分: 1. 非对称加密(公钥和私钥) 比特币使用非对称加密技术来确保交易的安全性。每个比特币…

Docker 浅谈重要的概念和应用场景

文章目录 一、重要的概念二、特性三、特性的常见应用场景四、基本使用流程 一、重要的概念 镜像&#xff08;Image&#xff09;&#xff1a;镜像是Docker的基本构建块&#xff0c;它是一个只读的文件&#xff0c;包含了运行应用程序所需的所有文件系统、库和依赖项。可以将镜像…

1065:奇数求和

【题目描述】 计算非负整数m到n(包括m和n)之间的所有奇数的和&#xff0c;其中&#xff0c;m 不大于 n&#xff0c;且n 不大于300。例如 m3,n12 其和则为&#xff1a;35791135。 【输入】 两个数 m 和n &#xff0c;两个数以一个空格分开&#xff0c;其中 0≤m≤n≤300 。 …

设计模式: 外观模式

文章目录 一、什么是外观模式二、外观模式结构1、外观模式的主要角色包括&#xff1a;2、外观模式通常适用于以下情况&#xff1a; 三、优点 一、什么是外观模式 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它提供了一个统一的接口&…

洛谷入门——P1567 统计天数

统计天数 题目描述 炎热的夏日&#xff0c;KC 非常的不爽。他宁可忍受北极的寒冷&#xff0c;也不愿忍受厦门的夏天。最近&#xff0c;他开始研究天气的变化。他希望用研究的结果预测未来的天气。 经历千辛万苦&#xff0c;他收集了连续 N ( 1 ≤ N ≤ 1 0 6 ) N(1 \leq N …

Java中Random

import java.util.Random;public class RandomExample {public static void main(String[] args) {Random random new Random();// 生成一个随机整数int randomNumber random.nextInt();System.out.println("Random number: " randomNumber);// 生成一个指定范围内…

python的stone音乐播放器的设计与实现flask-django-php-nodejs

该系统利用python语言、MySQL数据库&#xff0c;flask框架&#xff0c;结合目前流行的 B/S架构&#xff0c;将stone音乐播放器的各个方面都集中到数据库中&#xff0c;以便于用户的需要。该系统在确保系统稳定的前提下&#xff0c;能够实现多功能模块的设计和应用。该系统由管理…

Docker搭建mysql8的主从复制

Docker 通过Docker部署Mysql主从复制&#xff0c;Docker安装在前篇有&#xff0c;直接演示&#xff1a; 拉取镜像 # 获取有哪些镜像 docker search mysql# 拉取MySQL镜像 docker pull mysql:8.0.32# 查看镜像 docker images主节点的配置 创建数据存储目录 mkdir -p /docke…

python_BeautifulSoup爬取汽车评论数据

爬取的网站&#xff1a; 完整代码在文章末尾 https://koubei.16888.com/57233/0-0-0-2 使用方法&#xff1a; from bs4 import BeautifulSoup 拿到html后使用find_all()拿到文本数据&#xff0c;下图可见&#xff0c;数据标签为&#xff1a; content_text soup.find_all…

蓝桥杯/减肥/c\c++

问题描述 小明是一个大胖子&#xff0c;为了让体重达到正常水平&#xff0c;他的计划是&#xff1a;减掉n千克体重&#xff0c;分多周完成&#xff08;至少是2周&#xff09;&#xff0c;每周都减重正整数千克。为了激励自己&#xff0c;他决定每周减掉的体重都必须比上周减掉的…

006——GenericTimer(基于liteos-a)

目录 Generic Timer介绍 1.1 硬件结构 1.1.1 System Counter特性 1. 两种访问方式 2. CP15寄存器 3. MemoryMapped寄存器 1.1.2 Timer特性 1.2 SystemCounter时钟源 1.3 使用方法 GenericTimer源码分析 1.2 源码分析 1.2.1 初始化 1.2.2 启动Timer 1.2.3 中断处理…

SQPSK

文章目录 [1]张显辉,沈国松.SQPSK调制体制在跟踪与数据中继卫星中的应用[J].遥测遥控,2007(S1):26-29.[2]保骏.QPSK、SQPSK信号解调相位模糊及其对Viterbi译码的影响[J].四川兵工学报,2011,32(03):53-55.[3]赵辉,严晓芳,张玉. 星载SQPSK高速调制系统的设计[C]//中国通信学会.20…

内网穿透方案

内网穿透 有几种流行的内网穿透软件可供选择&#xff0c;它们都能帮助你在内网环境中建立与外部网络的连接。以下是其中一些常用的内网穿透软件&#xff1a; Ngrok&#xff1a;Ngrok 是一个简单易用的内网穿透工具&#xff0c;可以快速创建安全的公共 URL&#xff0c;让你可以…

在服务器上训练faster-rcnn模型(pycharm和Termius)

本文主要介绍使用服务器训练模型的两种方式&#xff1a;pycharm&#xff08;可视化界面友好&#xff09;and终端&#xff0c;本人用的是macos系统&#xff0c;可能pycharm某些入口的位置不一样&#xff0c;本教程代码以faster-rcnn为例 准备工作&#xff1a; 1.知道自己所用服…

力扣-字符串的最长公共前缀

1 采用纵向比较的方法&#xff0c;即以这个字符串数组的第一个字符串作为参照对象&#xff0c;纵向就是同时比较每个字符串的同样位置上的元素是否相同&#xff0c;所以外部循环负责控制走到哪个位置了&#xff0c;内部循环就把后面要比较的每个字符串的当前位置上的元素拿出来…

LeetCode 300. 最长递增子序列 题解(C,C++) (包含动态规划与贪心的区别的资料)

题目链接&#xff1a; - 力扣&#xff08;LeetCode&#xff09; 资源&#xff1a; 关于动态规划和贪心算法的区别&#xff0c;动态规划的常见题型&#xff0c;我总结了一些&#xff08;还有文档哦&#xff0c;持续更新&#xff0c;以后有扩充&#xff09;&#xff0c;大家可移…

外卖店优先级c++

题目 输入样例&#xff1a; 2 6 6 1 1 5 2 3 1 6 2 2 1 6 2输出样例&#xff1a; 1样例解释 6时刻时&#xff0c;1 号店优先级降到 3&#xff0c;被移除出优先缓存&#xff1b;2 号店优先级升到 6&#xff0c;加入优先缓存。 所以是有 1 家店 (2 号) 在优先缓存中。 思路 …

docker 安装部署 jenkins

今天 小☀ 给大家普及一下什么是 jenkins&#xff01;&#xff01; Jenkins是一个开源软件项目&#xff0c;基于Java开发的持续集成工具。它提供了一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。Jenkins起源于Hudson&#xff0c;主要用于持续、自动地构建、…

C语言 自定义类型:结构体

目录 前言 一、结构体类型 1.1 结构体的声明 1.2 结构体变量的创建和初始化 1.3 结构体的特殊声明 1.4 结构体的自引用 二、结构体的对齐 2.1 对齐规则 2.2 内存对齐的原因 2.3 修改默认对齐数 2.4 结构体传参 三、结构体实现位段 3.1 位段的内存分配 3.2 段的跨平…

我面了昆仑天工大模型算法岗,题是真硬啊。。。

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂同学、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…