为什么模板元编程(Template Metaprogramming)中要大量地使用递归方式?
Posted on 2005-01-11 21:36 andrew 阅读(1361) 评论(1) 收藏 举报对C++模板元编程有一些了解的朋友,想必都会有这样的感觉:为了达到某种目的,动辄
就要使用模板的递归定义,一个模板的定义之中嵌套着自身的实例化。比如,为了计算
n的阶乘,我们必须如此定义:
于是,我们可以很自然地写出下面的递归函数:
同时,也可以把该递归函数轻而易举地转化为迭代计算(即使用循环语句),例如:
这样一来,就引出了一个问题:能不能在模板元编程中也使用迭代的方式来计算阶乘呢?
毕竟在有些情况下,迭代比递归要简便直观。
遗憾的是,答案是否定的。为什么?现将原因分析如下:
C++模板元编程与普通的编程方式不同,它属于编译时刻(Compile-time)的程序设计,
而不是运行时刻的程序设计。
在C++中,我们进行编译时刻程序设计的手段主要有三个:
(1)模板:更确切地说,是模板的特化(Specialization),通过定义主模板、完全
特化模板和部分特化模板,我们获得了在编译时刻编写if-else语句的能力,但是并没有
获得编写循环语句的能力。
(2)编译时刻常整数的计算:让我们获得了在编译时刻进行求值计算的能力,但是,
有一点十分重要,所有在编译时刻计算出来的数值都是不可再改变的。例如,在定义了一个
枚举值之后你就不能再去改变它。
(3)typedef语句:可以为已知类型引入别名,但是,一旦别名定义之后,你也不能再去
改变它。
显然,以上三条都与迭代操作格格不入,迭代操作要求存在一个迭代器(即循环变量),然后
不断的改变该迭代器的值,直到满足某个条件位置(这时循环中止)。由于在编译时刻程序
设计中,根本找不到可以改变其值的实体,因此,无法实现迭代操作。
最后,得出的结论是:虽然C++是一种命令式程序设计语言,但是在模板元编程中,为了
进行编译时刻计算求值,不得不大量采用递归的方法。这倒是有些像纯函数式程序设计语言,
比如说Haskell,因为在这类语言中根本不存在变量的概念,所以更谈不上什么迭代了。
浙公网安备 33010602011771号