C++模版元编程

上传人:206****923 文档编号:51772829 上传时间:2018-08-16 格式:PPT 页数:52 大小:256.50KB
返回 下载 相关 举报
C++模版元编程_第1页
第1页 / 共52页
C++模版元编程_第2页
第2页 / 共52页
C++模版元编程_第3页
第3页 / 共52页
C++模版元编程_第4页
第4页 / 共52页
C++模版元编程_第5页
第5页 / 共52页
点击查看更多>>
资源描述

《C++模版元编程》由会员分享,可在线阅读,更多相关《C++模版元编程(52页珍藏版)》请在金锄头文库上搜索。

1、C+模板元编程技术与应用荣耀 动机让更多的C+程序员了解模板元编程,并在 此过程中获得快乐!目录* 历史 * 导入范例 * 主要思想 * 静态语言设施 * 控制结构 * 数据结构 * 数值计算* 类型计算 * 代码生成 * 断言和契约 * 库 * DSEL设计 * 结语 * 资源历史1994年,在圣迭哥举行的一次C+标准委员会会议期间, Erwin Unruh展示了一段特别的代码,可以在编译期以编译 错误信息的方式产生从2到某个给定值之间的所有质数。这份代码的原始版本见注5,修订版见注6。可以使用GCC编译器观 察到上述效果。同年夏天,Todd Veldhuizen受Erwin的例子启发,发现

2、可以 使用C+模板进行元编程(metaprogramming),并发表了 一份技术报告。次年5月又在C+ Report上发表了一篇名为 “Using C+ template metaprograms”的文章,从而将 Erwin Unruh发现的C+编译期模板编程(Compile-time Template Programming)进一步精化为C+模板元编程( Template Metaprogramming,TMP)。导入范例/ 主模板 template struct Fib enum Result = Fib:Result + Fib:Result ; ;/ 完全特化版 template s

3、truct Fib enum Result = 0 ; ;1.计算Fibonacci数列第N项/ 示例 int main() int i = Fib:Result;/ std:cout :Result; 被VC7.1编译成如下指令(Intel P4 CPU): 00411A1E mov dword ptr i,37h 字面量37h即为Fibonacci数列的第10项的值。可见,Fib:Result的 确被评估于编译期,结果作为处理器指令的一部分而被存储起来。运作机理:当编译器实例化Fib时,为了给其enum Result赋值,编译器需要对Fib和Fib进行实例化,同 理,又需要针对Fib和Fi

4、b实例化同样的模板,当 实例化到Fib和Fib的时候,完全特化版被实例化,至 此递归结束。这个处理过程类似于递归函数调用,编译器被 用于解释元程序,生成的结果程序中仅包含一个常量值。导入范例/ 主模板 template struct IfThenElse typedef T1 ResultType; ;/ 局部特化 template struct IfThenElse typedef T2 ResultType; ;/ 示例 IfThenElse:ResultType i; / i的类型为int2.类型选择基于给定的布尔常量表达式 在两个类型之中二选一。若 表达式为true,则T1被 type

5、def为ResultT,否则 ResultT代表T2。只针对模板参数的 局部进行特化。主要思想利用模板特化机制实现编译期条件选择结构,利用 递归模板实现编译期循环结构,模板元程序则由编 译器在编译期解释执行。静态语言设施模板元编程使用静态C+语言成分,编程风格类似于函数 式编程,其中不可以使用变量、赋值语句和迭代结构等。在模板元编程中,主要操作整型(包括布尔类型、字符类 型、整数类型)常量和类型。被操纵的实体也称为元数据 (Metadata)。所有元数据均可作为模板参数。其他元数据类型还包括枚举、函数指针/引用、全局对象的指针/引用 以及指向成员的指针等。另外,已经有一些编译期浮点数计算探索(

6、 参见注7)。由于在模板元编程中不可以使用变量,我们只能使用 typedef名字和整型常量。它们分别采用一个类型和整数值 进行初始化,之后不能再赋予新的类型或数值。如果需要 新的类型或数值,必须引入新的typedef名字或常量。静态语言设施编译期赋值通过整型常量初始化和typedef语句实现。例如:enum Result = Fib:Result + Fib:Result;或static const int Result = Fib:Result + Fib:Result;成员类型则通过typedef引入,例如:typedef T1 Result;新、旧编译器均支持静态语言设施条件结构采用模板

7、特化或条件操作符实现。如果需要从两个或更 多种类型中选其一,可以使用模板特化 ,如前述的IfThenElse。 可以使用条件操作符返回两个候选数值之一,例如: template struct Max enum Result = (a b) ? a : b ; ;静态C+代码使用递归而不是循环语句。递归的终结采用模板特 化实现。如果没有充当终结条件的特化版,编译器将一直实例化 下去,一直到达编译器的极限。C+标准建议编译器实现至少要支持17层实例化。大多数编译器支持的递归 实例化数目远不止17。例如,GCC支持多达500层递归模板实例化。C+静态语言设施是图灵完备的 ,理论上可以用于实现任何可实

8、 现的算法。可以使用模板元编程实现与运行期C+所对应的程序流程 控制结构。控制结构/ If / 主模板 template struct If;/ 完全特化版 template struct If static void F()/ 待执行的语句 ;/ 示例 If:F();主模板未必一 定要予以定义 。此主模板纯 粹供随后的特 化所用。控制结构/ For / 主模板 template struct For static inline void f()/ 待执行的语句For:f(); ;/ 完全特化版 template struct Switch static void f()/ 待执行的语句1 ;

9、/ 完全特化版2 template :Result:execute(); / 打印“Default“我们希望支持这 样的用法控制结构/ Switch const int DEFAULT = -1; struct NilCase;template struct Case enum tag = tag_;typedef Type_ Type;typedef Next_ Next; ;/ 主模板 template struct Switch private:typedef typename Case:Next NextCase;enum caseTag = Case:tag,found = (cas

10、eTag = tag | caseTag = DEFAULT); public:typedef typename IfThenElse:Result:ResultType Result; ;/ 局部特化 template struct Switch typedef NilCase Result; ;利用typename 消除歧义 如前述 类似地,可以分别给出更符合直觉的、结构性更好的For、 While、Do-While实现。控制结构最早提出编译期控制思想并给出雏形实现的是Todd Veldhuizen,参 见注1。Krysztof Czarnecki, Ulrich Eisenecker则实

11、现了更一般 化的编译期结构(如刚才展示的第二个版本的Switch)参见注12。可以使用嵌套模板实现复杂的编译期数据结构(编译期容 器),其中可以容纳整数和类型。考察两个例子:一个序列,为Loki库中的Typelist;一个是二 叉树(或树的二叉树表示)结构。数据结构Boost MPL库中定义有vector、deque、list、set以及map等序列, 它们都是编译期数据结构。数据结构/ Typelist template struct Typelist typedef T Head;typedef U Tail; ; / 计算长度 / 主模板 template struct Length;

12、/ 局部特化 template struct Length enum value = 1 + Length:value ; ; / 完全特化 template T; cout :value struct BTree / BTNode enum Value = N ;typedef Left_ Left;typedef Right_ Right; ;数据结构/ 判树是否为空/ 主模板 template struct IsEmpty;/ 局部特化 template struct IsEmpty enum Result = false ; ;/ 完全特化 template enum Result =

13、 true ; ;数据结构/ 示例typedef BTree tree1; typedef BTree tree2; typedef BTree, BTree tree3;int main() cout :Result :Result :Result aTree2;由于模板元编程最先是因为数值计算而被发现的,因此 早期的研究工作主要集中于数值计算方面,先锋是Todd Veldhuizen和Blitz+库。元编程在该领域最早的应用是实 现“循环开解(Unroll Loop)”。其他库(例如MTL、 POOMA等)也采用了这种技术。数值计算数值计算领域还有很多重要的模板元编程(相关)技术,例如“表

14、达 式模板(Expression Templates)”(见注2)、“部分求值( Partial Evaluation)”(见注3)等。数值计算/ 主模板 template struct DotProduct static T Result(T* a, T* b)return *a * *b + DotProduct:Result(a+1, b+1); ;/ 局部特化 template struct DotProduct static T Result(T* a, T* b)return *a * *b; ;一个经典的循环开解例子:计算向量点积算法思想:向量a和b的点 积=向量a和b首元素的乘

15、 积+剩余维度向量之点积一维向量的情形数值计算/ 示例 int main() int a5 = 1, 2, 3, 4, 5 ;int b5 = 6, 7, 8, 9, 10;cout :Result(a, b) :result(a,b) = *a * *b + DotProduct:result(a+1,b+1) = *a * *b + *(a+1) * *(b+1) + DotProduct:result(a+2,b+2) = *a * *b + *(a+1) * *(b+1) + *(a+2) * *(b+2) + DotProduct:result(a+3,b+3) = *a * *b + *(a+1) * *(b+1) + *(a+2) * *(b+2) + *(a+3) * *(b+3) + DotProduct:result(a+4,b+4) = *a * *b + *(a+1) * *(b+1) + *(a+2) * *(b+2) + *(a+3) * *(b+3) + *(a+4) * *(b+4)值得一提的一个模 板元编程陷阱长期以来,科学计算领域一直是Fortran的天下,采用运

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号