跟我学c++高级篇——c++模板元编程之十二c++11对模板元编程的支持和扩展

C++11模版元编程 模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程序的执行完全是在编译期,并且模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改,另外它用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else,for等语句都不能用。 阅读详情

一、模板元编程在c++中的发展

模板元编程从本质上看和函数编程有些类似。其实偏底层的语言就是有这个好处,怎么抽象怎么封包一下,就会和高级的语言或者其它应用方式感觉相同。c++的元编程,对每一个c++开发人员来说,都是一个很深的技术,会用和会写到会设计,这需要一个很长的时间才能达到。更不要提到最后融会贯通,自由收发。
模板元编程,其实在底层库或者框架中应用更多,这也是为什么很多c++开发人员为什么写了很多代码,工作了很长时间也没有没接触过的原因。毕竟,咱们国内的整体软件形式大家也都明白,拿来主义还是盛行。这里不谈此风好与坏,合适的就是最好的。
早期的元编程在知乎上有人挖过坟,是一个不能编译成功的例子,后来慢慢被一些牛人完善出来。它是一种不经意的过程,是一种模板编程的外溢。这种提法其实就是说明,它的编程模式和普通的模板编程模式是有区别的,这种区别就是不让一般开发者容易明白。包括在后来看到的SFINAE技术。当真,对大多数人来说,这不是技法,更像灾难。飞机很好用,但不会开。
c++的标准委员会当然不会坐视不理,毕竟,牛人自己写那个也麻烦啊,就像开飞机,不小心,飞机就要掉来来的感觉。所以基础设施不断的随着标准的升高而完善,从一些新的模板类和函数封装起来,减少复杂度增加易接受程度到干脆另起炉灶引入更新的概念和更好的基础设施。Concepts就是一个典型的例子。

二、c++11及以后续版本中的模板元编程

不可否认,相对于其它语言,c++语言本身的应用就是复杂的(灵活)。而模板编程则更上一层,正如有的人在网上所言,他们公司禁止使用模板。模板编程的难点对于初学者是非常不友好的,一个重要的体现点在于,模板的错误,即使非常小,也会有一大片的错误,可能大多数人一下子就晕了。那么可想而之,高手们眼中模板元编程是一门新语言的建议,能不让新手们望而却步么?更何况,它的应用范围又不大(虽然很底层,是一个重要的基础设施)。
这样看来,这不是c++标准委员会的大牛们想看的。毕竟,用得多,用得广,才会使c++更容易不断发展下去。那么在新的c++11及以上标准里就提供了大量的简化的元编程方法,大量的元函数被封装起来,直接被调用,更是在c++20推出了Concepts进一步简化相关的元编程的应用。
下面看几个提供的常用的元函数:

std::is_integral:整形检查
std::is_same:二者类型是否一致
std::integral_constant:包装特定数据类型,在bool时可用于元编程的分支控制
std::enable_if:根据第一个形参的bool值得确定第二个形参的公开成员typedef type是否使用
std::integer_sequence:这个在前面用过,元编程中产生整数序列(数组)

更多的请参考:https://en.cppreference.com/w/cpp/meta#Type_traits
元编程确实难,但只要坚持用,坚持思考,达到在实际中应用还是没有什么问题的。

三、应用和相关学习资料

讲了很多元编程的优点,但在实际应用中其实还是有不少困难的。最典型的就是两个:
1、开发,首先是一个编程习惯和开发思想的转换,包括设计思想,代码调试手段等等,都需要转变。另外前面提到过,元编程主要在库和框架中使用,而这点在国内恰恰又是短板中的短板(国内更强调用功能),所以互相学习的可能性以及获取帮助的可能性都很小。这就意味着出现问题,更多的依赖自己去查找资料。

2、应用,一般来说,开发一个动态库甚至一个框架,只要给个头文件说明基本就搞定了,而相关的算法和需要控制的代码都被安全的放在库里。而元编程采用模板技术,代码的实现目前基本只能在头文件中,也就是说,交出头文件的同时,源码就全暴露了。而模板的特性是不使用不编译,所以如果当使用一个头文件时或者多处使用时,就会发现编译时间增加了(当然,小规模的应用就忽略了)。同时,还有一个更重要的问题,一般应用方的很少有对技术掌握特别深的,这就意味着,给对方元编程的代码文件,如果没有详细的说明文档,对方可能会很排斥,毕竟模板本身就很复杂了,再加个元编程。

这里给大家推荐几本书,正如在前面介绍,学好c++模板元编程,其实主要有三本书可以做为打基础(有的是有多个版本也算一个),一个是《C++ Templates The Complete Guide》,这个第一版中有侯捷老师版本的,有陈伟柱老师版本的,最新又出来了第二版,可惜没有比较正式的中文版。另外一个是《Modern c++Design》中文版叫《c++设计新思维》;还有一个就是《c++模板元编程》(c++ Template Metaprogramming),这些书相对来说都比较老了。有一本国内牛人写的书《c++模板元编程实战》值得学学。
其它还有很多书籍,大家在学习完成上面的书后可以参考。网上也有很多牛人的相关的博客或者公众号,大家取其精华即可。
学习是一个漫长的过程,不要妄想一蹴而就。

四、例程

还以前面的函数判断为例子,就可以看出的版本前进引起的简化:
1、老版本

template <typename T, void (T::*)(const typename T::value_type&)>
struct IsHave;

template <typename T, void (T::*)(typename T::value_type)>
struct IsHas;

template <typename T>
bool ishas(...)
{
    return false;
}
template <typename T>
bool ishas(IsHave<T, &T::push_front>*)
{
    return true;
}
template <typename T>
bool ishas(IsHas<T, &T::push_front>*)
{
    return true;
}
int main()
{
    std::cout << ishas<std::list<int> >(NULL) << std::endl;
    std::cout << ishas<std::vector<int> >(NULL) << std::endl;
    return 0;
}

看上去还是有点复杂,但是它和前面的must判断原理是一样的,通过替换是否成功来决定结果。

2、c++11版本
c++11版本就简单不少,看下面的例子:

template <typename>
using void_t = void;

template <typename T, typename V = void>
struct IsHave :std::false_type {};

template <typename T>
struct IsHave<T, void_t<decltype(std::declval<T>().push_front(std::declval<typename T::value_type>()))>> :std::true_type {};

int main()
{
    std::cout << IsHave<std::list<int>>::value << std::endl;
    std::cout << IsHave<std::vector<int>>::value << std::endl;
    return 0;
}

这个相对上面就更简单更容易理解,而且更灵活。

3、c++20更新版本
在concept推出后,这个版本更简化了,前面有太多的例子了,这里就不再重复,有兴趣可以根据前面的再结合此例子写一下。

五、总结

模板元编程写到这里,暂时先告一个段落。基本的元编程的技术都覆盖到了,更深或者更抽象的设计这个需要不断的迭代理论和实践,不断的紧跟着c++标准前进。可能以前复杂的方式在高版本的c++标准里就是简单的一两行代码,但是这两行代码恰恰是前面复杂实现过程中不断总结抽象出来的经验。
不断自省,不断前进,不断挑战自我,与诸君共勉。

C++模板元编程详细教程(之十一) 《C++模板元编程详细教程》系列的第11篇,也是完结篇,主要介绍了visit的实现方法、C++的模板范式,以及一些Q&A和感悟 阅读详情

相关推荐

Vue2项目实战:海康威视WEB无插件开发包V3.4从下载到多画面预览(附完整代码)

本文详细介绍了在Vue2项目中集成海康威视WEB无插件开发包V3.4实现多画面监控预览的完整实战方案。内容涵盖从开发包下载、Nginx代理配置、核心组件封装到多画面并发加载与性能优化的全流程,并提供了完整的代码示例,帮助开发者高效解决浏览器无插件播放与多路视频流加载的难题。

c7d8e9的博客 320

【C++】C++11(万能模版、完美转发,可变参数模版,lambda表达式,包装器function+bind绑定)

定义了一个可以调用的对象 / 匿名函数,一般定义在局部,特点是可以深度绑定了局部的数据。lambda表达式,实际上是一个匿名函数,实际上是在定义一个函数(局部的函数)lambda表达式通常是用来定义小函数lambda表达式在局部是很好用的,最特别的就是捕捉列表Add叫lambda表达式的对象 – lambda定义的是一个对象。lambda表达式书写格式:lambda表达式各部分说明:捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数。

ZZZCCC的博客 1598

BLDC六步换相驱动实战:从霍尔真值表到PWM调速的代码实现

本文详细解析了BLDC六步换相驱动原理,从霍尔真值表解读到PWM调速的代码实现,提供了基于STM32的实战方案。重点介绍了霍尔信号解码、换相状态机设计以及PWM动态调速策略,帮助开发者快速掌握无刷电机驱动技术。

weixin_28273593的博客 211

突破编程_C++_C++11新特性(模板的改进与细节)

C++11 新特性:模板的改进与细节

突破编程 1744

深入解析CAN2.0A与CAN2.0B协议:帧格式与通信机制对比

本文深入对比了CAN2.0A与CAN2.0B协议的核心差异,重点解析了11位标准帧与29位扩展帧的帧格式、标识符长度及通信机制。文章阐述了CAN2.0B向下兼容的特性,并探讨了在汽车电子、工业控制等复杂网络中,如何根据项目需求、兼容性及实时性要求,在标准帧与扩展帧之间做出合理选择。

weixin_29163797的博客 394

Wider Face+YOLOV7人脸检测

使用Wider Face数据集训练YOLOV7

chen_znn的博客 8407

C++11实现模板化(通用化)RAII机制

什么是RAII?RAII(Resource Acquisition Is Initialization),也称直译为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的机制。 C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。 RAII 机制就是利用了C++的上述特性,在需要获取使用资源RES的时候,构造一个临时对象(T),在其构造T时获取资源,在T生命期控

10km的专栏 1万+

51单片机STC8G1K08驱动ws2812记录

使用51单片机控制17个2812灯,这里选择STC8芯片,最大频率可以达到35M,参考网上的各种文章案例,使用定时器做的时候实测做不到规格书要求的245-345ns,STC8G1K08不带PWM,所以只能使用nop来做,好在单片机在这里只有做编程灯的功能,省略测试过程,下面是程序,使用的是24MHz内部晶振 //设置一个灯珠 void SendOnePix(unsigned char *ptr) { unsigned char i,j; unsigned char temp; fo...

的博客 7320

跟我学C++中级篇——编译期和运行时的性能处理分析

本文探讨了C++性能优化的两种主要方式:运行时优化和编译期优化。运行时优化包括多态处理、条件语句和表处理等方法,各有其优缺点,如多态处理编写复杂且性能较低,而表处理性能较好但对开发者要求较高。编译期优化通过C++新标准(如constexpr、模板元编程等)显著提升性能,如std::visit利用编译期多态、表机制和内联优化等特性。通过合理结合这两种优化方式,开发者可根据实际需求提升程序性能。

fpcc的专栏 1209

Claude Code 100个真实案例 - 用AI搭建LangChain多工具Agent(自主搜索+查询)

本案例展示如何使用 Claude Code 搭建一个 LangChain 多工具 Agent 系统。Agent 能够自主决定调用搜索引擎、数据库查询、天气查询、计算器等工具,像人类助手一样拆解问题并逐步解决。

yueyeguzhuo的专栏 560

树根互联Java开发面试题及参考答案

说一下 Java 集合类。 Java 集合类是用于存储和操作一组对象的容器。它提供了多种数据结构,方便程序员对数据进行高效的管理和处理。 Java 集合框架主要包括两大接口:Collection 和 Map。 Collection 接口是一组对象的集合,它有三个主要的子接口:List、Set 和 Queue。 List 接口代表有序的集合,可以包含重复的元素。例如 ArrayList,它是基于数组实现的动态数组。它的优点是随机访问效率高,通过索引访问元素的时间复杂度为 O (1)。当

大模型大数据攻城狮的专栏 856

跟我学C++中级篇—static_assert和assert

对c++中的编译期断言和运行时断言进行分析说明

fpcc的专栏 501

【数据集8】全球人口数据WorldPop详解

全球人口数据WorldPop详解

WW、forever的博客 7881

跟我学C++中级篇——编译期的条件选择

对编译期时C++编译器各种条件选择的处理

fpcc的专栏 222

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

跟我学C++中级篇—编译期检查

对编译期的相关检查进行分析说明

fpcc的专栏 350

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++11 元编程 判断是否有std::hash<T>特例并提供hash函数通用实现

std::hash的用途std::hash是C++11提供的一元函数模板,用于向标准库提供返回数据类型T哈希值(hash value)的哈希函数(hash function)。 std::hash只是定义了一个一元操作符operator(),接受一个T类型的参数,返回一个size_t类型的哈希值, C++11为所有基本类型(basic types)都提供了特例化实现: C

10km的专栏 5859

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C++模板编程高级技巧

因此,模板的实现也应该放在头文件内,此时在其他代码文件中可以直接将模板的实现也包含进来,当需要生成模板实例时,编译器可根据已知模板实现当场生成,从而无需依赖在别的目标文件中生成的模板实例。标记,并且在函数及类模板的实现中,模板参数是用于指代具体类型,因此,这两个关键字标记类型的模板参数被称为类型模板参数,除此之外,还有以下四种类型。以上四种参数统称为非类型模板参数,其在模板参数列表中的声明方式与对应类型的变量声明一致,此外模板参数还可以是一个模板,称为模板模板参数。或者给定一个迭代器类型,求出其标签类型)

遇事不决,问春风 956

(二)模板元编程简介

元编程(meta-programming)也被称为“超程序”,“超编程”或“产生式编程”,这样说法一定程度上反映了其本质——它是一种位于普通程序之上、超越普通程序的程序,可以操纵、产生程序的程序。模板元编程本质上是泛型编程的一个子集,从广义上来说,所有使用template 的泛型代码都可以称作元程序——因为泛型编程代码并不是真正可编译执行的代码,它们只是定义了代码的产生规则,是用来生成代码的“模板”。然而模板元编程又不完全等同于泛型编程,它是一种“函数式编程”,是图灵完备的,可以“计算”任何东西。

icc_hhy的博客 1827

突破编程_C++_高级教程(模板编程的高级特性)

C++ 高级教程:模板编程的高级特性

突破编程 1655

C++高级编程(五)模板

模板:属于泛型编程,泛型编程指的是代码“重用”,固定的代码但是其内部函数、对象类型或类可以不同。1、函数模板函数模板的声明形式为:template(参数表){    函数体}#include using namespace std; template void add(T a, Y b) { cout <<(int)a<<"+"<<(int)b<<"=" << a + b << endl;

程序猿的视界 1632

C++模板

cpp

pcj2007的专栏 655

C++11:模板元编程(TMP)基础

模板元编程(Template Metaprogramming, TMP)是的技术。它通过将逻辑从运行时转移到编译期,实现高性能的类型安全和代码生成。

bigger_belief的博客 522

C++11 扩展 - 模板元编程

摘要:模板元编程(TMP)是现代C++在编译时进行计算和代码生成的高级技术,通过模板特化、递归实例化和类型操作实现零运行时开销的优化。文章从核心概念、基础语法、类型萃取、SFINAE等方面系统讲解TMP,并介绍C++11/14/17/20对TMP的增强特性,如constexpr函数、变量模板、if constexpr等。TMP具有零运行时开销、类型安全等优点,但也存在编译时间长、学习成本高等缺点。随着C++20引入概念(concepts)和模块(modules),模板元编程正朝着更简洁、更高效的方向发展。

Small_entreprene的博客 990
上一篇: 领域驱动设计——柔性设计
下一篇: DPDK系列之九虚拟化vhost
fpcc
fpcc 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄22年 4039粉丝 1188原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值