C++模板元模板(异类词典与policy模板)- - - 题目答案
目录
一、书中第一题
二、书中第三题
三、书中第五题
四、书中第六题
五、书中第七题
六、书中十一题
七、书中十二题
八、 书中十三题
总结
一、书中第一题
#include <iostream>template <typename T, size_t N>
struct NSVarTypeDict {static void Create_() {CreateHelper<N, T>();}private:template <size_t M, typename U>struct CreateHelper {static void Apply() {// 构造元素的逻辑std::cout << "Constructing element at index " << M << std::endl;CreateHelper<M - 1, U>::Apply();CreateHelper<M - 1, U>::Apply();}};template <typename U>struct CreateHelper<0, U> {static void Apply() {// 基础情况:当索引为0时停止递归}};
};int main() {NSVarTypeDict<int, 8>::Create_();return 0;
}
二、书中第三题
#include <iostream>
#include <type_traits>template <size_t N, size_t M, typename T1, typename T2>
struct NSVarTypeDict {using NewTupleType_ = std::conditional_t<N == M, T1, T2>;
};int main() {struct Type1 {int value;};struct Type2 {double value;};typename NSVarTypeDict<3, 4, Type1, Type2>::NewTupleType_ var1; // 选择Type2typename NSVarTypeDict<5, 5, Type1, Type2>::NewTupleType_ var2; // 选择Type1return 0;
}
- 代码结构更清晰:通过使用std::conditional_t将特化1和特化2合并成一个表达式,避免了重复的代码逻辑和声明。
- 可维护性提高:合并后的代码更加简洁,易于阅读和理解。
在使用std::conditional_t进行合并后,简化的代码更易于理解和维护,并且避免了重复代码的问题,因此整体上更具优势。
三、书中第五题
#include <iostream>class VarTypeDict {
public:template<typename T>void Set(T&& value) && {// 只能用于右值的Set函数实现std::cout << "Setting value for rvalue: " << value << std::endl;}template<typename T>void Set(T& value) & {// 能用于左值的Set函数实现std::cout << "Setting value for lvalue: " << value << std::endl;}
};int main() {VarTypeDict::Values values;int x = 10;values.Set(x); // 调用能用于左值的Set函数values.Set(20); // 调用只能用于右值的Set函数return 0;
}
优势和劣势:
优势:
- 能用于左值的函数可以接受左值类型的参数,提供更灵活的使用方式。
- 通过重载的方式,程序可以根据传入值的类型来选择合适的函数重载,提高了程序的通用性和适用性。
劣势:
- 在某些情况下,程序员需要知道传入的值是左值还是右值,否则会导致调用不符合预期的函数。
总体上,能用于左值的函数相比只能用于右值的函数更加灵活,可以接受更多种类的参数,但需要谨慎使用以避免潜在的问题。
四、书中第六题
将构造函数的访问权限从public修改为private或protected是一种有效的封装手段,可以限制其它类对构造函数的直接访问,从而更好地控制类的实例化。
理由:
- 控制类的实例化:通过将构造函数的访问权限设为private或protected,可以防止该类被直接实例化,从而强制使用特定的接口或方法来获取该类的实例。
- 封装实现细节:将构造函数的访问权限限制在类内部,有助于隐藏实现细节,提高类的封装性和安全性。
- 限制子类的实例化:将构造函数的访问权限设为protected可以使子类能够调用构造函数,但限制外部代码直接实例化子类。
接下来,让我们尝试将Values的构造函数访问权限从public修改为private,然后编译检查是否符合预期。
class VarTypeDict {
public:class Values {private: // 修改构造函数的访问权限为privateValues() {}friend class VarTypeDict; // 允许VarTypeDict类访问构造函数public:template<typename T>void Set(T&& value) && {std::cout << "Setting value for rvalue: " << value << std::endl;}template<typename T>void Set(T& value) & {std::cout << "Setting value for lvalue: " << value << std::endl;}};
};
根据上述代码修改,我们将Values的构造函数的访问权限修改为private,并使用friend关键字允许VarTypeDict类访问构造函数。
在实际编译时,会发现尝试在外部进行Values类的实例化会导致编译错误,而在VarTypeDict类中可以正常调用构造函数来创建Values的实例,符合我们的预期。
这种修改符合我们的预期,成功限制了外部代码对Values类的直接实例化,增强了类的封装性和安全性。
五、书中第七题
#include <iostream>
#include <tuple>class VarTypeDict {
public:class Values {private:std::tuple<int, double, std::string> data; // 使用std::tuple替换指针数组public:template<typename T>void Set(T&& value) && {std::get<T>(data) = value; // 使用std::get获取元素}template<typename T>T Get() {return std::get<T>(data); // 使用std::get获取元素}};
};
示例中,使用std::tuple替换了指针数组,这样就不需要显式进行内存分配和释放。通过std::get函数,我们可以在不了解具体元素类型的情况下,访问和操作特定类型的元素。
新版本的复杂度分析:
- 时间复杂度:使用std::tuple并不会增加操作的时间复杂度,因为std::tuple内部通常是通过继承和模板特化来实现的,因此元素访问的操作也是常数时间复杂度。
- 空间复杂度:使用std::tuple可能会略微增加一些内存消耗,因为std::tuple通常会引入一些辅助结构来实现元素访问的功能。
总体而言,通过使用std::tuple替换指针数组,新版本的VarTypeDict复杂度并未明显增加,并且更加安全和易用,因为不再需要显式操作内存分配与释放,同时使用std::tuple提供了更好的类型安全性和代码可读性。
六、书中十一题
#include <iostream>// 定义策略类模板
template <typename T>
class Policy {
public:void DoSomething() {std::cout << "Doing something with type " << typeid(T).name() << std::endl;}
};// 定义宏来简化策略对象的定义
#define POLICY_POLICY(PolicyType, ValueType) Policy<PolicyType<ValueType>>int main() {// 构造模板策略对象POLICY_POLICY(std::vector, int) policyObject;// 使用策略对象policyObject.DoSomething();return 0;
}
七、书中十二题
#include <iostream>
#include <type_traits>
#include <utility>class NamedParameters {
public:class Values {private:int value;public:Values(int val) : value(val) {}template<typename T>T Get() const {return T(value); // 复制构造返回值}template<typename T>typename std::remove_const<T>::type&& Get() && {return std::move(value); // 返回右值引用,使用移动语义}};
};int main() {NamedParameters::Values values(123);// 使用左值引用调用Get函数int copyValue = values.Get<int>();std::cout << "Copy Value: " << copyValue << std::endl;// 使用右值引用调用Get函数int&& moveValue = std::move(values).Get<int>();std::cout << "Move Value: " << moveValue << std::endl;return 0;
}
示例中,我们在NamedParameters::Values类中引入了一个新的Get函数模板,并使用std::remove_const来移除返回类型的const限定符。在Get函数的右值引用版本中,我们使用std::move对底层数据对象进行移动,通过移动语义返回右值引用。这样,对于右值引用的情况,我们可以通过移动来返回底层数据对象,减少了额外的复制成本。
在主函数中,我们首先使用左值引用调用Get函数,对底层数据对象进行复制。然后,我们使用std::move将values对象转换为右值引用,并调用Get函数获取右值引用的底层数据对象。通过输出的结果,我们可以看到使用移动语义获取的值。
通过引入移动语义的Get函数,我们可以根据NamedParameters::Values对象的左值或右值特性,使用不同的方式返回底层数据对象,从而减少复制带来的额外消耗。
八、 书中十三题
#include <iostream
#include <type_traits>// 定义异类词典模板
template<typename... Ts>
struct VarTypeDict {};// 添加元素的元函数 AddItem
template <typename Dict, typename NewItem>
struct AddItem;// 特化:向空的异类词典添加元素
template <typename NewItem>
struct AddItem<VarTypeDict<>, NewItem> {using type = VarTypeDict<NewItem>;
};// 特化:向非空的异类词典添加元素
template <typename Head, typename... Tail, typename NewItem>
struct AddItem<VarTypeDict<Head, Tail...>, NewItem> {using type = typename std::conditional<std::is_same<Head, NewItem>::value, VarTypeDict<Head, Tail...>, typename AddItem<VarTypeDict<Tail...>, NewItem>::type>::type;
};// 删除元素的元函数 DelItem
template <typename Dict, typename ItemToDelete>
struct DelItem;// 特化:从空的异类词典删除元素,报错
template <typename ItemToDelete>
struct DelItem<VarTypeDict<>, ItemToDelete> {static_assert(sizeof(ItemToDelete) == 0, "Item does not exist in VarTypeDict");
};// 特化:从包含元素的异类词典删除元素
template <typename Head, typename... Tail, typename ItemToDelete>
struct DelItem<VarTypeDict<Head, Tail...>, ItemToDelete> {using type = typename std::conditional<std::is_same<Head, ItemToDelete>::value, VarTypeDict<Tail...>, typename AddItem<typename DelItem<VarTypeDict<Tail...>, ItemToDelete>::type, Head>::type>::type;
};int main() {// 使用示例:添加元素using MyDict = VarTypeDict<struct A, struct B>;using DictWithMoreItems = typename AddItem<MyDict, struct C>::type;using DictWithLessItems = typename DelItem<MyDict, A>::type;// 使用示例:删除不存在的元素,会报错// using DictWithInvalidDel = typename DelItem<MyDict, C>::type; // 会产生编译时错误std::cout << typeid(DictWithMoreItems).name() << std::endl; // 输出 VarTypeDict<A, B, C>std::cout << typeid(DictWithLessItems).name() << std::endl; // 输出 VarTypeDict<B>return 0;
}
示例中,我们定义了AddItem和DelItem两个元函数来实现添加和删除元素。通过模板特化和递归调用,我们可以实现对异类词典的元素操作。在DelItem的特化中,我们使用静态断言来检测是否要删除的元素存在于异类词典中,以便在编译时发现错误。
在主函数中,我们使用示例展示了AddItem与DelItem元函数的使用方式,并输出了修改后的异类词典类型。同时,我们还展示了尝试删除不存在的元素时会触发编译时错误的情况。
通过这种方式,我们可以在编译期间操作异类词典的元素,动态地修改异类词典的类型。
总结
下一章开始学习深度学习简介!!!
相关文章:
C++模板元模板(异类词典与policy模板)- - - 题目答案
目录 一、书中第一题 二、书中第三题 三、书中第五题 四、书中第六题 五、书中第七题 六、书中十一题 七、书中十二题 八、 书中十三题 总结 一、书中第一题 #include <iostream>template <typename T, size_t N> struct NSVarTypeDict {static void Cre…...
二十三种设计模式全面解析-组合模式与迭代器模式的结合应用:构建灵活可扩展的对象结构
在前文中,我们介绍了组合模式的基本原理和应用,以及它在构建对象结构中的价值和潜力。然而,组合模式的魅力远不止于此。在本文中,我们将继续探索组合模式的进阶应用,并展示它与其他设计模式的结合使用,以构…...

postgresql|数据库|提升查询性能的物化视图解析
前言: 我们一般认为数字的世界是一个虚拟的世界,OK,但我们其实有些需求是和现实世界一模一样的,比如,数据库尤其是关系型数据库,希望在使用的数据库能够更快(查询速度),…...

Unity中Shader雾效的原理
文章目录 前言一、我们先看一下现实中的雾二、雾效的混合公式最终的颜色 lerp(雾效颜色,物体颜色,雾效混合因子) 三、雾效的衰减1、FOG_LINEAR(线性雾衰减)2、FOG_EXP(指数雾衰减1)3、FOG_EXP(指数雾衰减2) 前言 Unity中Shader雾…...
chatgpt辅助论文优化表达
chatgpt辅助论文优化表达 写在最前面最终版什么是好的论文整体上:逻辑/连贯性细节上一些具体的修改例子 一些建议,包括具体的提问范例1. **明确你的需求**2. **提供上下文信息**3. **明确问题类型**4. **测试不同建议**5. **请求详细解释**综合提问范例&…...
Vue3 源码解读系列(二)——初始化应用实例
初始化应用实例 创建 Vue 实例对象 createApp 中做了两件事: 创建 app 对象保存并重写 mount /*** 创建 Vue 实例对象*/ const createApp ((...args) > {// 1、创建 app 对象,延时创建渲染器,优点是当用户只依赖响应式包的时候࿰…...

网络原理-UDP/TCP详解
一. UDP协议 UDP协议端格式 由上图可以看出,一个UDP报文最大长度就是65535. • 16位长度,表示整个数据报(UDP首部UDP数据)的最大长度(注意,这里的16位UDP长度只是一个标识这个数据报长度的字段࿰…...

C#多线程入门概念及技巧
C#多线程入门概念及技巧 一、什么是线程1.1线程的概念1.2为什么要多线程1.3线程池1.4线程安全1.4.1同步机制1.4.2原子操作 1.5线程安全示例1.5.1示例一1.5.2示例二 1.6C#一些自带的方法实现并行1.6.1 Parallel——For、ForEach、Invoke1.6.1 PLINQ——AsParallel、AsSequential…...

c primer plus_chapter_four——字符串和格式化输入/输出
1、strlen();const;字符串;用c预处理指令#define和ANSIC的const修饰符创建符号常量; 2、c语言没有专门储存字符串的变量类型,字符串被储存在char类型的数组中;\0标记字符串的结束&a…...
Python Fastapi+Vue+JWT实现注册、登录、状态续签【登录保持】
文章目录 一、实现流程1.注册2.登录3.登录保持【状态续签】二、实现方法1.注册2.登录+登陆状态保持* 后端部分* 前端部分一、实现流程 1.注册 Created with Raphal 2.3.0...

oracle-sql语句解析类型
语句执行过程:1. 解析(将sql解析成执行计划) 2.执行 3.获取数据(fetch) 1. shared pool的组成。 share pool是一块内存池。 主要分成3块空间。free, library(库缓存,缓存sql以及执行计划),row cache(字典缓存) select * from v…...

2023 年最新企业微信官方会话机器人开发详细教程(更新中)
目标是开发一个简易机器人,能接收消息并作出回复。 获取企业 ID 企业信息页面链接地址:https://work.weixin.qq.com/wework_admin/frame#profile 自建企业微信机器人 配置机器人应用详情 功能配置 接收消息服务器配置 配置消息服务器配置 配置环境变量…...
3、FFmpeg基础
1、FFmpeg 介绍 FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库。 2、FFmpeg 组成 - libavformat:用于各种音视频[封装…...

c语言:用指针解决有关字符串等问题
题目1:将一个字符串str的内容颠倒过来,并输出。 数据范围:1≤len(str)≤10000 代码和思路: #include <stdio.h> #include<string.h> int main() {char str1[10000];gets(str1);//读取字符串内容char* p&str1[…...

吃透 Spring 系列—Web部分
目录 ◆ Spring整合web环境 - Javaweb三大组件及环境特点 - Spring整合web环境的思路及实现 - Spring的web开发组件spring-web ◆ web层MVC框架思想与设计思路 ◆ Spring整合web环境 - Javaweb三大组件及环境特点 在Java语言范畴内,web层框架都是基于J…...
JAVA后端服务端与移动端客户端高精度时间同步思路
一、脑补 在Chrome--->Network----> Timing中可以查看一个请求在各个阶段所花费的时间。 Timing中各个字段的意思发: 1、Queueing:从增加到等待处理队列到实际开始处理的时间间隔——浏览器也有线程机制,所有的请求不能同时发送&…...
nsd的资料
nsd是一款开源的DNS服务器应用。 近期参与项目过程中,涉及到DNS业务,结果被打的满头包。 虽然在校学习时就知道DNS协议,但从业这么多年,对于DNS协议的理解其实一直处于一知半解的状态。 当前处理问题时,接触到了nsd&am…...

关于Maven中pom.xml文件不报错但无法导包解决方法
问题 我的pom文件没有报红,但是依赖无法正常导入。 右下角还总出现这种问题。 点开查看报错日志。大致如下 1) Error injecting constructor, java.lang.NoSuchMethodError: org.apache.maven.model.validation.DefaultModelValidator: method <init>()V no…...
使用决策树分类
任务描述 本关任务:使用决策树进行分类 相关知识 为了完成本关任务,你需要掌握:1.使用决策树进行分类 使用决策树进行分类 依靠训练数据构造了决策树之后,我们可以将它用于实际数据的分类。在执行数据分类时,需要…...

STM32H563烧录后无法擦除
STM32H563烧录后无法擦除,使用STM32CubeProgrammer连接后显示如下图所示。...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...