C++模板元模板实战书籍讲解第一章题目讲解
目录
第一题
C++代码示例
第二题
C++代码示例
第三题
3.1 使用std::integral_constant模板类
3.2 使用std::conditional结合std::is_same判断
总结
第四题
C++代码示例
第五题
C++代码示例
第六题
C++代码示例
第七题
C++代码示例
总结
第一题
对于元函数来说,数值与类型其实并没有特别明显的差异:元函数的输入可以是数值或类型,对应的变换可以在数值与类型之间进行。比如可以构造一个元函数,输入是一个类型,输出是该类型变量所占空间的大小---------这就是一个典型的从类型变换为数值的元函数。尝试构造该函数,并测试是否能行。
C++代码示例
#include <iostream>
#include <type_traits>template <typename T>
struct TypeSize {static constexpr size_t value = sizeof(T);
};int main() {std::cout << TypeSize<int>::value << std::endl; // 输出:4(int 类型在大多数平台上占用4个字节)std::cout << TypeSize<double>::value << std::endl; // 输出:8(double 类型在大多数平台上占用8个字节)std::cout << TypeSize<char>::value << std::endl; // 输出:1(char 类型在大多数平台上占用1个字节)return 0;
}
输出结果:
代码详解:
在上面的代码中,我们定义了一个名为TypeSize
的模板结构体,它有一个静态成员变量value
,其默认值是sizeof(T)
,其中T
是TypeSize
的模板参数类型。通过sizeof
运算符,我们可以在编译时获取类型T
的大小,并将其保存在value
中。
在main
函数中,我们分别测试了int
、double
和char
类型的大小,并使用std::cout
输出结果。可以看到,对于每个类型,我们都成功地获取了其在内存中所占空间的大小。
第二题
作为进一步的扩展,元函数的输入参数甚至可以是类型与数值混合的。尝试构造一个元函数,其输入参数为一个类型以及一个整数。如果该类型所对应对象的大小等与该整数,那么返回true,否则返回false。
C++代码示例
#include <iostream>
#include <type_traits>template <typename T, size_t N>
struct CheckSize {static constexpr bool value = sizeof(T) == N;
};int main() {std::cout << std::boolalpha;std::cout << CheckSize<int, 4>::value << std::endl; // 输出:true(int 类型在大多数平台上占用4个字节)std::cout << CheckSize<double, 8>::value << std::endl; // 输出:true(double 类型在大多数平台上占用8个字节)std::cout << CheckSize<char, 2>::value << std::endl; // 输出:false(char 类型在大多数平台上占用1个字节)return 0;
}
输出结果:
代码详解:
我们使用了一个元函数 CheckSize
,结构体 CheckSize
接受两个模板参数:类型 T
和大小 N
。在元函数中,我们使用 sizeof
运算符计算类型 T
的大小,并将其与整数 N
进行比较。如果相等,则元函数的静态成员变量 value
设置为 true
,否则设置为 false
。
第三题
3.1 使用std::integral_constant
模板类
#include <iostream>
#include <type_traits>template <typename T, size_t N>
struct CheckSize : std::integral_constant<bool, sizeof(T) == N> {};int main() {std::cout << std::boolalpha;std::cout << CheckSize<int, 4>::value << std::endl; // 输出:true(int 类型在大多数平台上占用4个字节)std::cout << CheckSize<double, 8>::value << std::endl; // 输出:true(double 类型在大多数平台上占用8个字节)std::cout << CheckSize<char, 2>::value << std::endl; // 输出:false(char 类型在大多数平台上占用1个字节)return 0;
}
使用std::integral_constant
模板类来实现元函数CheckSize
。CheckSize
结构体继承自std::integral_constant
,并提供两个模板参数:bool
类型表示返回类型,以及sizeof(T) == N
作为值。通过继承自std::integral_constant
,我们可以从CheckSize<T, N>
直接访问value
成员变量。
3.2 使用std::conditional
结合std::is_same
判断
#include <iostream>
#include <type_traits>template<typename T, size_t N>
struct CheckSize {static constexpr bool value = std::is_same_v<sizeof(T), N>;
};int main() {std::cout << std::boolalpha;std::cout << CheckSize<int, 4>::value << std::endl; // 输出:true(int 类型在大多数平台上占用4个字节)std::cout << CheckSize<double, 8>::value << std::endl; // 输出:true(double 类型在大多数平台上占用8个字节)std::cout << CheckSize<char, 2>::value << std::endl; // 输出:false(char 类型在大多数平台上占用1个字节)return 0;
}
使用了std::conditional
结合std::is_same
检查类型大小。std::is_same_v
是一个用于判断两个类型是否相同的模板,sizeof(T)
表示类型 T
的大小,在此和 N
进行比较。如果两者相同,则value
被设置为 true
,否则被设置为 false
。
总结
这些是更特殊或不太常见的元函数表示形式,这些形式可能适用于某些特定的使用场景或要求。
第四题
本章讨论了以类模板作为元函数的输出,尝试构造一个元函数,它接收输入后会返回一个元函数,后者接收输入后会再返回一个元函数------这仅仅是一个联系,不必过于在意其应用场景
C++代码示例
#include <iostream>
#include <functional>template <typename Input>
struct FirstLayer {template <typename Func>struct SecondLayer {template <typename... Args>constexpr auto operator()(Args&&... args) const {return Func{}(std::forward<Args>(args)...);}};template <typename Func>constexpr auto operator()(Func) const {return SecondLayer<Func>{};}
};struct MyFunction {template <typename... Args>constexpr auto operator()(Args&&... args) const {return sizeof...(Args);}
};int main() {FirstLayer<int> first;auto second = first(MyFunction{});std::cout << second(1, 2, 3, 4, 5) << std::endl; // 输出:5(返回传入参数的数量)return 0;
}
输出结果:
代码详解:
示例中,FirstLayer
是一个元函数,它接收一个输入类型 Input
。FirstLayer
结构体中定义了一个内部模板结构体 SecondLayer
,它接收一个元函数类型 Func
。SecondLayer
结构体中定义了一个函数调用运算符 operator()
,它接收任意参数 Args...
,并通过调用 Func
来实现对元函数的调用。
FirstLayer
还定义了一个函数调用运算符 operator()
,它接收一个元函数类型 Func
,并返回一个 SecondLayer<Func>
对象,即返回一个闭包(closure)元函数。
在 main()
函数中,我们先创建一个 FirstLayer<int>
对象 first
。然后,我们通过调用 first(MyFunction{})
来传递一个 MyFunction
元函数对象,得到一个 SecondLayer
对象 second
。最后,我们通过调用 second
来调用传入的 MyFunction
元函数,并传递参数 1, 2, 3, 4, 5
。
运行示例代码后,将输出 5
,表示传入的参数数量为 5。
这个示例就是一个接收输入并返回元函数的元函数的实现。当 FirstLayer
元函数接收一个输入类型后,它返回一个闭包元函数 SecondLayer
。你可以继续调用 SecondLayer
元函数,并传递其他的元函数来实现更多的函数组合和操作。
第五题
使用SFINAE构造一个元函数:输入一个类型T,当T存在子类型type时该元函数返回true,否则返回false。
C++代码示例
#include <iostream>
#include <type_traits>template <typename T>
struct HasType {// 检查 SFINAE 的辅助函数template <typename U>static std::true_type test(typename U::type*);template <typename U>static std::false_type test(...);static constexpr bool value = decltype(test<T>(nullptr))::value;
};// 测试用例
struct A {using type = int;
};struct B {};int main() {std::cout << std::boolalpha;std::cout << HasType<A>::value << std::endl; // 输出:true(A 类型存在名为 type 的子类型)std::cout << HasType<B>::value << std::endl; // 输出:false(B 类型不存在名为 type 的子类型)return 0;
}
输出结果:
代码详解:
示例中,HasType
是一个元函数,用于检查类型 T
是否具有名为 type
的子类型。我们先定义了两个辅助函数 test
,一个接收具有 type
子类型的输入类型 U
(使用 typename U::type*
作为函数参数),另一个使用 ...
表示可变参的占位符。在 HasType
元函数中,test<T>(nullptr)
这一表达式启用了 SFINAE 机制,如果传递的类型具有名为 type
的子类型,则会选择第一个辅助函数进行调用,否则会选择第二个辅助函数。使用 decltype
和 std::true_type
、std::false_type
来从辅助函数的返回类型中提取布尔值。
在测试用例中,我们分别检查了类型 A
和类型 B
。因为类型 A
存在名为 type
的子类型,所以 HasType<A>::value
的结果为 true
。而类型 B
不存在名为 type
的子类型,所以 HasType<B>::value
的结果为 false
。
第六题
使用在本章中学到的循环代码书写方式,编写一个元函数,输入一个类型数组,输出一个无符号整形数组,输出数组中的每个元素表示输入数组中相应类型变量的大小。
C++代码示例
#include <iostream>
#include <utility>
#include <array>template <typename... Types>
struct SizeOfArray;// 基本情况:处理空类型数组
template <>
struct SizeOfArray<> {using type = std::array<std::size_t, 0>;
};// 递归情况:处理非空类型数组
template <typename T, typename... Types>
struct SizeOfArray<T, Types...> {using type = std::array<std::size_t, sizeof...(Types)+1>;
};// 辅助函数,打印无符号整型数组
template <std::size_t N, std::size_t... Sizes>
void printSizes(const std::array<std::size_t, N>& sizes, std::index_sequence<Sizes...>) {((std::cout << sizes[Sizes] << ' '), ...);std::cout << std::endl;
}int main() {using MyTypes = std::tuple<int, double, bool, char>;using Sizes = typename SizeOfArray<int, double, bool, char>::type;Sizes sizes;sizes[0] = sizeof(int);sizes[1] = sizeof(double);sizes[2] = sizeof(bool);sizes[3] = sizeof(char);printSizes(sizes, std::make_index_sequence<sizes.size()>()); // 输出:4 8 1 1return 0;
}
输出结果:
代码详解:
在这段代码中,我们定义了一个 SizeOfArray
结构体,用于计算类型数组的大小。它通过递归方式处理类型数组,当类型数组为空时,返回一个大小为 0 的 std::array
,当类型数组非空时,返回一个大小为 sizeof...(Types)+1
的 std::array
,其中 sizeof...(Types)
是类型数组的元素个数。
在 main
函数中,我们定义了一个类型数组 MyTypes
,其中包含了 int
、double
、bool
和 char
类型。然后,我们使用 SizeOfArray
结构体计算 MyTypes
数组中各个类型的大小,并将它们存储在 Sizes
结构体中。
接下来,我们使用 sizeof
操作符获取每个类型的大小,并将它们存储在 sizes
数组中的相应位置。
最后,我们调用 printSizes
函数,打印 sizes
数组中的每个元素。这里使用了 std::make_index_sequence
来生成一个索引序列,使得我们可以使用折叠表达式在 printSizes
函数中依次访问 sizes
数组中的元素。
第七题
使用分支短路逻辑实现一个元函数,给定一个整数序列,判断其中是否存在值为1的元素。如果存在,就返回true,否则返回false
C++代码示例
#include <iostream>// 终止条件,判断最后一个元素是否等于 1
template <int Last>
bool hasOne() {return Last == 1;
}// 递归情况,判断当前元素是否等于 1,并继续判断后面的元素
template <int First, int Second, int... Rest>
bool hasOne() {return (First == 1) || hasOne<Second, Rest...>();
}int main() {bool result1 = hasOne<1, 2, 3, 4>(); // 序列中存在值为1的元素,返回truebool result2 = hasOne<2, 3, 4, 5>(); // 序列中不存在值为1的元素,返回falsestd::cout << "Result 1: " << std::boolalpha << result1 << std::endl;std::cout << "Result 2: " << std::boolalpha << result2 << std::endl;return 0;
}
输出结果:
代码详解:
第一个版本是终止条件,用于判断最后一个元素是否等于1。在这个版本中,我们只有一个模板参数 Last
,当 Last
等于 1 时,返回 true
。
第二个版本是递归情况,用于判断当前元素是否等于1,并继续判断后面的元素。在这个版本中,我们有三个模板参数,分别代表当前元素 First
、下一个元素 Second
,以及剩余的元素 Rest...
。在递归调用时,我们将 Second
作为新的 First
,并继续判断后面的元素。
通过这段代码,我们可以正确判断整数序列中是否存在值为1的元素。
在 main
函数中,我们使用两个示例来测试 hasOne
元函数。第一个示例传入的序列为 <1, 2, 3, 4>
,其中存在值为1的元素,因此返回 true
。第二个示例传入的序列为 <2, 3, 4, 5>
,其中不存在值为1的元素,因此返回 false
。
总结
后续会开始陆续更新第二章,如果有需要博主讲解其他书也可以私信我!!!
相关文章:

C++模板元模板实战书籍讲解第一章题目讲解
目录 第一题 C代码示例 第二题 C代码示例 第三题 3.1 使用std::integral_constant模板类 3.2 使用std::conditional结合std::is_same判断 总结 第四题 C代码示例 第五题 C代码示例 第六题 C代码示例 第七题 C代码示例 总结 第一题 对于元函数来说,…...
Java在互联网网络安全中的应用(三)
目录 1. 互联网网络安全概述 2. Java的网络安全特性 3. 用Java加固网络应用 4. 安全传输 5. 安全框架和工具 6. 实际应用案例 7. 最佳实践和资源 目标 本次技术分享的目标是介绍Java技术在互联网网络安全中的应用,包括关键概念、最佳实践和实际案例。 1. 互…...
VMLogin如何解决跨境电商多账号管理难题?
做跨境电商的,比如亚马逊、eBay这些卖家。随着团队规模的扩大,或者多店铺运营,那么多个店铺多个账号管理就成为了一个困难。如何解决这个问题呢? 首先来看看很多电商卖家多账号管理会面临的问题 经营者通常需要同时管理多个市场…...

STM32创建工程步骤
以创建led工程为例: 新建一个led文件夹 新建一个以led命名的工程(用keil_uVision5)并添加三个组。 Library文件夹里放置库函数文件。 User: 点亮led灯的程序; 直接给寄存器赋值 调用库函数。 #include "stm…...
软考 系统架构设计师系列知识点之边缘计算(1)
所属章节: 第11章. 未来信息综合技术 第4节. 边缘计算概述 1. 边缘计算概念 在介绍边缘计算之前,有必要先介绍一下章鱼。章鱼就是用“边缘计算”来解决实际问题的。作为无脊椎动物中智商最高的一种动物,章鱼拥有巨量的神经元,但…...
vue:写一个数组box和list数组,在保留box数组中原有对象的同时,将list数组中每一个对象插入到box数组后面
前言:由于源码涉及到后端调用数据和一些无关的功能所以我就专门针对这个功能的代码,这样好方便理解。 1、在data中定义两个数组:box和list,并给它们初始化值 data() {return {box: [/*初始的box数组对象*/],list: [/*初始的list…...

Python教程:随机函数,开始猜英文单词的游戏
开始猜英文单词的游戏… 总计生命次数:3次 -----------游戏开始中…----------- ????请猜一个,4位数的单词:mafr 猜错了,再努力一下 -----------你还有2次生命------------ ma?&…...

Unit2_1:动态规划DP
文章目录 一、介绍二、0-1背包问题问题描述分析伪代码时间复杂度 三、钢条切割问题问题描述分析伪代码过程 四、矩阵链乘法背景性质分析案例伪代码 一、介绍 动态规划类似于分治法,它们都将一个问题划分为更小的子问题 最优子结构:问题的最优解包含子问题的最优解。DP适用的原…...

k8s提交spark应用消费kafka数据写入elasticsearch7
一、k8s集群环境 k8s 1.23版本,三个节点,容器运行时使用docker。 spark版本时3.3.3 k8s部署单节点的zookeeper、kafka、elasticsearch7 二、spark源码 https://download.csdn.net/download/TT1024167802/88509398 命令行提交方式 /opt/module/spark…...

linux傻瓜式安装Java环境及中间件
linux配置Java环境及中间件 1.傻瓜式安装Java1.下载2.追加3.刷新测试 2.傻瓜式安装docker1.docker卸载2.docker安装 3.Docker傻瓜式安装Redis1.傻瓜式安装安装并配置 4.Docker傻瓜式安装RabbitMQ5.Docker傻瓜式安装MySql1.拉取2.配置 6.傻瓜式安装Nacos1.官网下载nacos2.SQL文件…...

javascript中的new原理及实现
在js中,我们通过new运算符来创建一个对象,它是一个高频的操作。我们一般只是去用它,而很少关注它是如何实现的,它的工作机制是什么。 1 简介 本文介绍new的功能,用法,补充介绍了不加new也同样创建对象的方…...

R语言 PPT 预习+复习
什么狗吧发明的结业考,站出来和我对线 第一章 绪论 吊码没有,就算考R语言特点我也不背,问就是叫么这没用。 第二章 R语言入门 x<-1:20 赋值语句 x 1到20在x上添加均值为0、标准差为2的正态分布噪声 y <- x rnorm (20, 0, 2) 这…...
轻松实现固定资产智能管理的工具来了
易点易动资产管理系统是一款旨在轻松实现智能资产管理的工具。固定资产管理对于企业的日常经营和可持续发展至关重要。然而,固定资产具有设备价值高、使用周期长、使用地点分散、使用环境恶劣、流动性强、安全管理难度大等特点,传统的管理方式往往无法高…...
软考高级系统架构设计师系列之:微服务
软考高级系统架构设计师系列之:微服务 一、微服务二、微服务的优势三、微服务挑战四、微服务与SOA的对比一、微服务 微服务架构建议将大型复杂的单体架构应用划分为一组微小的服务,每个微服务根据其负责的具体业务职责提炼为单一的业务能力。每个服务可以很容易地部署并发布…...

vue + axios + mock
参考来源:Vue mock.js模拟数据实现首页导航与左侧菜单功能_vue.js_AB教程网 记录步骤:在参考资料来源添加axios步骤 1、安装mock依赖 npm install mock -D //只在开发环境使用 下载完成后,项目文件package.json中的devDependencies就会加…...

Mongoose 开源库--json 使用笔记
一、 json相关API mongoose 开源库可以使用json进行数据处理。 ①创建json字符串 // A helper macro for printing JSON: mg_snprintf(buf, len, "%m", MG_ESC("hi")) #define MG_ESC(str) mg_print_esc, 0, (str) char *mg_mprintf(const char *fmt, ...)…...
linux中复制文件如何排除一个目录
误区: 首先使用cp命令的 --exclude参数实不可取的,会造成以下的报错,因为cp命令中压根就没有--exclude这个参数的配置 cp: unrecognized option --exclude‘****’ 问题解决: 我们可以使用rsync工具来完成目录排除的功能&#x…...

时空智友企业信息管理系统任意文件读取漏洞复现
简介 时空智友企业信息管理系统是一个用于企业流程管理和控制的软件系统。它旨在帮助企业实现流程的规范化、自动化和优化,从而提高工作效率、降低成本并提升管理水平。 时空智友企业信息管理系统存在任意文件读取漏洞,攻击者可以在未授权的情况下读取…...

YOLOv8优化:block系列篇 | Neck系列篇 |可重参化EfficientRepBiPAN优化Neck
🚀🚀🚀本文改进: 可重参化EfficientRepBiPAN优化Neck 如何在YOLOv8下使用:1)结合neck; 🚀🚀🚀EfficientRepBiPAN在各个领域都有ying 🚀🚀🚀YOLOv8改进专栏:http://t.csdnimg.cn/hGhVK 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1.原理…...

零代码编程:用ChatGPT批量提取flash动画swf文件中的mp3
文件夹:C:\迅雷下载\有声绘本_flash[淘宝-珍奥下载]\有声绘本 flash,里面有多个flash文件,怎么转换成mp3文件呢? 可以使用swfextract工具从Flash动画中提取音频,下载地址是http://www.swftools.org/download.html,也…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...