C++高阶:元编程(Metaprogramming)--入门篇

模板元编程(Template Meta programming,TMP)

就是面向模板编程,把计算过程从运行时提前到编译期,提升性能;
区别于泛型编程(利用模板实现“安全的宏”)

应用场景: 编译期 数值计算类型计算、代码循环展开

思考题
用装饰器模式给存在已久的多个类(xx_config类)添加新功能: 读取 json/yaml/xml/ini 配置文件对应部分数据到本类私有成员(不同数量和类型)。就是用一句话添加新功能,注释这句话后,新功能消失

特点

  • 模板执行完全在编译期

  • 操作的数据对象只能是常量(如enum,静态常量,基本数据类型,自定义数据类型),
    不能是运行期的变量,不能用 if else for while;

  • 其计算能力受到具体编译器实现的限制(如递归嵌套深度,C++98 要求至少 17,C++11 要求至少 1024)

技巧

  • if-else逻辑可用 type_traits(类型特征)实现在编译期做判断,计算、查询、转换、选择
  • for 逻辑可用递归、重载、继承、偏特化 实现

一、核心概念:元函数(不是一个函数,功能类似函数)

(根据模板传参分为:“类型type”元函数,“值value”元函数)
函数三要素:返回值,调用方式,参数

约定 :
对于’类型’元函数,将保存返回结果的类型别名用 ::type 命名
对于’值’元函数,将保存返回结果的静态成员用 ::value 命名

1、“值”元函数: 模板传参是‘值’

#include <iostream>using namespace std;// 功能:求两个数的最大公约数
// 主模板:递归调用(关键点1),class 可以换成 struct
template < unsigned M, unsigned N > // 1.元函数的参数: 模板参数
class gcd {   // 元函数(不是一个函数,元函数发生在编译期,而通常函数调用发生在运行时)
public:static constexpr int value = gcd< N, M%N >::value; // 2.元函数的返回值:类模板的静态成员常量
};
// 特化模板:处理边界(关键点1)
template< unsigned M >
class gcd< M, 0 > {
public:static_assert(M != 0);static constexpr int value = M;
};int main() {// 3.元函数的调用 通过::访问类模板的成员int value=gcd<12,6>::value; // 值作为模板参数  cout << value << endl;      // 输出 6
}

2、“类型”元函数: 模板传参是‘类型’,普通函数做不到

#include <iostream>
using namespace std;// 功能:返回给定类型数组的维度
// 主模板, struct 可以换成 class + public:
template< typename T >
struct dim { static constexpr size_t value = 0u;}; // 当类型不是数组类型时,返回0// 特化1: 递归也可以放在特化中,而不一定在主模板中
template< typename U, size_t N >
struct dim< U[N] > { static constexpr size_t value = 1u + dim< U >::value; };
// 特化2
template< typename U >
struct dim< U[] > { static constexpr size_t value = 1u + dim< U >::value; };int main() {using array_t = int[10][20][30]; // 类型别名int arrry_dim = dim<array_t>::value; // 类型作为模板参数cout << "维度 = " << arrry_dim << endl; // 维度 = 3
}

对上面的优化版(这种更常见)

// 标准库中有一个值叫 value 的静态成员常量元函数
template <typename T, T v> struct integral_constant { static constexpr T value = v; /*....*/ };// 下面几个继承 integral_constant, 就有静态成员 value 了
template <typename T>
struct dim : integral_constant<std::size_t, 0u> {};template <typename U, std::size_t N>
struct dim <U[N]> : integral_constant<std::size_t, 1u + dim<U>::value > {};template <typename U>
struct dim <U[]>  : integral_constant<std::size_t, 1u + dim<U>::value > {};

3、“类型”元函数: 模板返回值是‘类型’,普通函数做不到

// 功能:返回移除 const 限定符的相同类型
template<typename T>
struct remove_const { using type = T; // 没有const 正常返回
};template<typename T>
struct remove_const<T const> { using type = T; // 移除了const 的相同类型
};

对上面的优化版(这种更常见)

template <typename T> struct type_is { using type = T; };   // 返回传入的类型, 统一命名 type// 下面几个继承 type_is, 就有 type 了
template <typename T> struct remove_const: type_is< T > {}; // 没有 const 正常返回
template <typename T> struct remove_const<T const> : type_is< T > {}; // 移除了 const 的相同类型
// 举一反三:下面是 移除顶层 volatile 限定符
template <typename T> struct remove_volatile: type_is< T > {}; // 没有 volatile 正常返回
template <typename T> struct remove_volatile<T volatile> : type_is< T > {}; // 移除了 volatile 的相同类型

二、模板中 if-else 逻辑

三、模板中 for 逻辑

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

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

相关文章

delphi中自定义自己的定时器

最近用上了rpt工具&#xff0c;但是用rpt自带的工具执行起一些定时任务不方便&#xff0c;有些功能不能自主&#xff0c;于是我在delphi中用定时器制作了自己的定时执行程序。 1、首先在窗体中放一个timer对象 2、在窗体的formcreate事件中加入以下关键代码&#xff0c;让定时器…

flask web学习之模板(一)

文章目录 一、模板基本用法1.1 定界符1.2 模板语法1.3 渲染模板 二、模板辅助工具2.1 上下文2.2 全局对象2.3 过滤器2.4 测试器2.5 模板环境对象 在动态web程序中&#xff0c;视图函数返回的HTML数据往往需要根据相应的变量&#xff08;比如查询参数&#xff09;动态生成。当HT…

Spring 与 Spring Boot:深入解析

Spring 与 Spring Boot&#xff1a;深入解析 前言: 欢迎来到本篇博客&#xff0c;今天我们将深度挖掘 Java 开发领域的两个主要框架——Spring 和 Spring Boot。尽管它们之间有着紧密的联系&#xff0c;但在某些方面却存在显著的区别。让我们逐步深入&#xff0c;挖掘它们的特…

【React系列】React中的CSS

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. React中的css方案 1.1. react 中的 css 事实上&#xff0c;css 一直是 React 的痛点&#xff0c;也是被很多开发…

接了一条路由器视频广告

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 2023年7月&#xff0c;松松团队荣幸的承接了“某口袋路由器”的短视频广告。 我们向客户索取了了几个卖点&#xff1a; 1.家用美观不用走线(无线小巧美观) 外出便携(出差、户外直播、露营等&#xff0c;只要充满电…

基于深度学习大模型实现离线翻译模型私有化部署使用,通过docker打包开源翻译模型,可到内网或者无网络环境下运行使用,可以使用一千多个翻译模型语言模型进行翻译

基于深度学习大模型实现离线翻译模型私有化部署使用,通过docker打包开源翻译模型,可到内网或者无网络环境下运行使用,可以使用一千多个翻译模型语言模型进行翻译,想要什么语种直接进行指定和修改就行。 环境要求,电脑内存低于8G建议不要尝试了,有无GPU都可以运行,但是有…

SpringBoot3多数据源动态切换

demo使用的时SpringBoot3.x、JDK17、MybatisPlus3.5.x、MySQL8 从数据中加载数据源 定义接口&#xff0c;指定数据源&#xff0c;从不同数据库获取数据 创建数据源表&#xff0c;用于指定不同数据源&#xff0c;程序自动动态获取 项目版本依赖关系 demo中所用到的工具以及…

宝塔安装的imagemagick不能用,必须自己手动安装

1 安装 用composer安装 2 宝塔安装的imagemagick不能用&#xff0c;必须自己手动安装&#xff08;3.4.3版本 php 7.3&#xff09; 1 步骤&#xff1a; wget https://pecl.php.net/get/imagick-3.4.3.tgz tar -zxf imagick-3.4.3.tgz cd imagick-3.4.3 /www/server/php/73…

代码+视频,手把手教你R语言使用forestploter包绘制单组及双组森林图

森林图在论文中很常见&#xff0c;多用于表示多因素分析中的变量与结果变量的比值效应&#xff0c;可以用图示的方法比较直观的绘制出来。既往我们在文章《R语言快速绘制多因素回归分析森林图&#xff08;1&#xff09;》已经介绍了怎么绘制森林图&#xff0c;但是绘图比较简单…

开启Android学习之旅-2-架构组件实现数据列表及添加(kotlin)

Android Jetpack 体验-官方codelab 1. 实现功能 使用 Jetpack 架构组件 Room、ViewModel 和 LiveData 设计应用&#xff1b;从sqlite获取、保存、删除数据&#xff1b;sqlite数据预填充功能&#xff1b;使用 RecyclerView 展示数据列表&#xff1b; 2. 使用架构组件 架构组…

Python从入门到网络爬虫(内置函数详解)

前言 Python 内置了许多的函数和类型&#xff0c;比如print()&#xff0c;input()等&#xff0c;我们可以直接在程序中使用它们&#xff0c;非常方便&#xff0c;并且它们是Python解释器的底层实现的&#xff0c;所以效率是比一般的自定义函数更有效率。目前共有71个内置函数&…

lambda表达式使用和示例

lambda表达式 什么是lambda 学习lamdba有两个结构十分关键&#xff0c;一个是lamdba自己&#xff0c;另一个是函数式接口 lamdba lamdba表达式本质上就是匿名方法&#xff0c;不能独立运行用于实现函数式接口定义的另一个方法&#xff0c;因此lamdba会产生一个匿名类lamdba…

全球海洋数据 (GLODAP) v2.2023(海洋碳数据产品)

全球海洋数据分析项目 (GLODAP) v2.2023 全球海洋数据分析项目 (GLODAP) v2.2023 代表了海洋生物地球化学瓶数据合成方面的重大进步。此更新主要关注海水无机碳化学&#xff0c;以 GLODAPv2.2022 为基础&#xff0c;包含多项关键增强功能。值得注意的是&#xff0c;增加了 43 …

CISSP 第9章:安全脆弱性、威胁和对策

第九章 安全脆弱性、威胁和对策 9.1 评估和缓解安全脆弱性 9.1 硬件 处理器 执行类型 多任务处理&#xff1a; 同时处理两个或更多任务 多处理&#xff1a; 利用多个处理器完成一个应用程序的处理能力 多程序设计&#xff1a;通过操作系统对单个处理器上的两个任务进行协调&…

Node.js+Express+Mysql实现分页查询

根据记录数总数和分页数获到页总数 function pageCount (totalnum,limit){return totalnum > 0 ? ((totalnum < limit) ? 1 : ((totalnum % limit) ? (parseInt(totalnum / limit) 1) : (totalnum / limit))) : 0; } 接收请求代码 router.get(/api/user/page, asy…

自动驾驶货车编队行驶系统功能规范

货车编队行驶功能规范 Truck Platooning Functional Specification 目录 1 概述... 7 1.1 目的... 7 1.2 范围... 7 1.3 术语及缩写... 7 1.4 参考法规标准... 8 2 功能规范... 9 2.1 功能描述... 9 2.1.1 功能用途…

简述DIV元素和SPAN元素的区别

DIV和SPAN是两种常见的HTML元素&#xff0c;DIV是块元素&#xff0c;默认换行&#xff0c;一般用于排版。SPAN是行内元素&#xff0c;默认不换行&#xff0c;一般用于局部文字样式。通过DISPLAY他们之间可以相互转换&#xff0c;DIV默认是BLOCK&#xff0c;SPAN默认是INLINE. 它…

代码随想录day9-KMP算法

title: 代码随想录Day9 date: 2024-01-04 19:38:32 代码随想录笔记 categories:技术 代码随想录day9-KMP算法|28. 找出字符串中第一个匹配项的下标 宏观 本来使用暴力 O(m*n)的算法&#xff0c;通过KMP方法&#xff0c;基于前缀表构建失败函数next数组&#xff0c;在失败后进…

centos6后台启动docker

如果您正在使用 Docker 1.7 并且希望使用 sudo docker -d --storage-drivervfs & 命令在 CentOS 6 上后台运行 Docker&#xff0c;但发现它没有按预期工作&#xff0c;这里有一些建议可以尝试&#xff1a; 确保使用正确的语法&#xff1a;在 Docker 1.7 中&#xff0c;-d 或…

计算机系统的性能指标

1.字长和数据通路宽度 字长&#xff1a;字长指的是计算机中一个数据字的长度。一个数据字是计算机中进行运算和存储的最小单位&#xff0c;通常由多个二进制位&#xff08;比如8位、16位、32位等&#xff09;组成。 举个例子&#xff0c;假设一个计算机的字长为8位&#xff0…