我在五年多前发现了模板元编程,并且在阅读现代C++设计方面获得了巨大的成功,但我从未发现在现实生活中使用它的机会.
有你曾经使用在实际代码这种技术?
Boost的贡献者无需申请; o)
Eric.. 27
我曾经在C++中使用模板元编程来实现一种称为"符号扰动"的技术,用于处理几何算法中的退化输入.通过将算术表达式表示为嵌套模板(即基本上通过手工写出解析树),我能够将所有表达式分析交给模板处理器.
使用模板执行此类操作比使用对象编写表达式树并在运行时进行分析更有效.它更快,因为修改后的(扰动的)表达式树可以在与代码的其余部分相同的级别上用于优化器,因此您可以在表达式中获得优化的全部好处,但也可以(在可能的情况下)在表达式和周围的代码.
当然,您可以通过为表达式实现一个小型DSL(特定于域的语言)并将已翻译的C++代码粘贴到常规程序中来完成相同的任务.这将为您带来所有相同的优化优势,也更加清晰 - 但需要权衡的是您必须维护解析器.
我曾经在C++中使用模板元编程来实现一种称为"符号扰动"的技术,用于处理几何算法中的退化输入.通过将算术表达式表示为嵌套模板(即基本上通过手工写出解析树),我能够将所有表达式分析交给模板处理器.
使用模板执行此类操作比使用对象编写表达式树并在运行时进行分析更有效.它更快,因为修改后的(扰动的)表达式树可以在与代码的其余部分相同的级别上用于优化器,因此您可以在表达式中获得优化的全部好处,但也可以(在可能的情况下)在表达式和周围的代码.
当然,您可以通过为表达式实现一个小型DSL(特定于域的语言)并将已翻译的C++代码粘贴到常规程序中来完成相同的任务.这将为您带来所有相同的优化优势,也更加清晰 - 但需要权衡的是您必须维护解析器.
我发现在Modern C++ Design中描述的策略在两种情况下非常有用:
当我开发一个我希望可以重用的组件时,但方式略有不同.Alexandrescu关于使用策略来反映设计的建议在这里非常合适 - 它帮助我解决了类似的问题,"我可以通过后台线程做到这一点,但如果有人后来想要在时间片中做到这一点怎么办?" 好吧,我只是编写我的类来接受ConcurrencyPolicy并实现我现在需要的那个.然后至少我知道跟在我后面的人可以在需要时编写并插入新的策略,而不必完全重写我的设计.警告:有时我必须自己统治,否则这可能会失控 - 记住YAGNI原则!
当我试图将几个类似的代码块重构为一个时.通常,代码将被轻微地复制粘贴和修改,因为否则会有太多if/else逻辑,或者因为涉及的类型太不同.我发现策略通常允许一个干净的"一刀切"版本,传统逻辑或多重继承不会.
我已经在游戏图形代码的内部循环中使用它,你需要某种程度的抽象和模块化但却无法支付分支或虚拟调用的成本.总的来说,这是一个比手写的特殊功能扩散更好的解决方案.
模板元编程和表达模板在科学界变得越来越流行,作为优化方法,在保持一些抽象的同时将一些计算工作卸载到编译器上.结果代码更大,可读性更低,但我使用这些技术来加速FEM库中的线性代数库和正交方法.
对于特定应用的阅读,Todd Veldhuizen是该领域的一个大牌.一本流行的书是Daoqi Yang的C++和面向对象的科学家和工程师数字计算.
编写c ++ 库时,模板元编程是一种很棒的强大技术.我已经在自定义解决方案中使用了一些时间,但通常不太优雅的旧式c ++解决方案更容易通过代码审查并且更容易为其他用户维护.
但是,在编写可重用的组件/库时,我已经从模板元编程中获得了很多好处.我并没有说任何像Boost那么大的东西,只是会经常重复使用的小部件.
我将TMP用于单例系统,用户可以在其中指定所需的单例类型.界面非常基础.在它下面由重型TMP提供动力.
template< typename T > T& singleton(); template< typename T > T& zombie_singleton(); template< typename T > T& phoenix_singleton();
另一个成功的用途是简化我们的IPC层.它采用经典的OO风格打造.每条消息都需要从抽象基类派生并覆盖一些序列化方法.没有什么太极端,但它产生了很多锅炉板代码.
我们向它扔了一些TMP,并为仅包含POD数据的消息的简单情况自动生成所有代码.TMP消息仍然使用OO后端,但它们大大减少了锅炉板代码的数量.TMP还用于生成消息vistor.随着时间的推移,我们所有的消息都迁移到了TMP方法.为消息传递构建一个简单的POD结构更容易,代码更少,并且添加少量(可能是3行)获取TMP生成类所需的行比导出一条新消息以在IPC中发送常规类更简单框架.
我一直使用模板元编程,但在D中,不是C++.C++的模板元语言最初是为简单类型参数化而设计的,并且几乎是偶然的,变成了图灵完整的元语言.因此,只有安德烈·亚历山大·斯特雷斯(Andrei Alexandrescu)才能使用它,而不仅仅是凡人.
另一方面,D的模板子语言实际上是为简单类型参数化之外的元编程而设计的.Andrei Alexandrescu 似乎很喜欢它,但其他人实际上可以理解他的D模板.它也足够强大,有人在其中编写了一个编译时光线跟踪器作为概念证明.
我想在D中写过的最有用/非平凡的元程序是一个函数模板,给定一个struct类型作为模板参数,列表中的列标题名称对应于结构中的变量声明作为运行时参数,将读取CSV文件,并返回一个结构数组,每行一个,每个结构字段对应一列.所有类型转换(字符串到float,int等)都是根据模板字段的类型自动完成的.
另一个很好用,但仍然没有正确处理一些情况,是一个深度复制函数模板,可以正确处理结构,类和数组.它只使用编译时反射/内省,因此它可以使用结构,与完整的类不同,它在D中没有运行时反射/内省功能,因为它们应该是轻量级的.
大多数使用模板元编程的程序员通过boost等库来间接使用它.他们甚至不知道幕后发生了什么,只是它使得某些操作的语法更加容易.