元编程

元编程(Metaprogramming)是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在运行时完成部分本应在编译时完成的工作。很多情况下与手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。

反射是促进元编程的一种很有价值的语言特性。把编程语言自身作为头等对象(如LispRebol)也很有用。支持泛型编程的语言也使用元编程能力。
元编程通常有两种方式起作用。一种方式是通过应用程序接口(API)来暴露运行时引擎的内部信息。另一种方法是动态执行包含编程命令的字符串。因此,“程序能编写程序”。虽然两种方法都能用,但大多数方法主要靠其中一种。
 
一个简单元编程的例子是使用bash脚本的产生式编程示例:
#!/bin/bash
# metaprogram
echo '#!/bin/bash' >program
for ((I=1; I<=992; I++)) do
echo "echo $I" >>program
done
chmod +x program
这个脚本(或程序)生成了一个新的993行程序来打印1至992。这只是演示用代码来写更多代码,并不是打印数字的最有效方法。然而,一个程序员可以几分钟内编写和执行元程序,却生成了近1000行代码。
==========
C++中也可以使用模板来进行元编程(以下代码在VC2008中编译通过):
#include<iostream>
using namespace std;
int Result;
//主模板
template<int N> //模板
class Fibonacci
{
public:
enum{Result = Fibonacci<N-1>::Result + Fibonacci<N-2>::Result };
//枚举,带有隐含计算
};
//完全特化模板
template<>
class Fibonacci<1> //带常参数1的构造函数
{
enum { Result = 1 };
//给枚举赋初值1
};
//完全特化模板
template<>
class Fibonacci<0> //带参数0的模板
{
public:
enum { Result = 0 };
//给枚举赋初值0
};
int main()
{
std::cout << "第20项的Fibonacci数是:" << Fibonacci<20>::Result << std::endl;
//隐含计算
system("pause");
return 1;
}
该示例定义了一个类模板,类中声明了一个枚举类型,该程序的奥秘就在枚举类型的构造上。从枚举类型的构造可以看出,他自身有一个样俺的迭代计算。两个构造函数为枚举类型初始化了数列的初始值,当调用“Fibonacci<20>::Reasult“时,就以这两个初始值为基础进行迭代。因此,程序在运行时并没有显示的计算,而是在编译时就由编译器计算了。
当编译器实例化Fibonacci<20>时,为了给其enum Result赋值,编译器需要对Fibonacci<19>和Fibonacci<18>进行实例化,之后同理······,当实例化到Fibonacci<1>和Fibonacci<0>的时候,完全特化模板被实例化,至此迭代结束。
所以,该程序编译的结果仅包含一个常量值,输出如下:
第20项的Fibonacci数是:6765
 
元编程是:关于程序的程序、操纵代码的程序。
应用:编译时计算、补充类型系统、基于模板的计算
优点:增强代码重用,编译时计算,不占用运行时cpu。
缺点:代码可读性较差,调试困难,编译时间延长,局限性(数值计算)
主要思想:利用模板特化机制实现编译期条件选择结构,利用递归模板实现编译期循环结构,模板元程序则由编译器在编译期解释执行。
模板元编程使用静态c++语言成分,编程风格类似于函数式编程,其中不可以使用变量、赋值语句和迭代结构等。
在模板元编程中,主要操作整形(包括布尔类型、字符类型、整数类型)常量和类型。被操纵的实体也称为元数据。所有元数据均可作为模板参数。

posted on 2016-03-17 20:47  月未央  阅读(310)  评论(0编辑  收藏  举报

导航