C++摸板元编程

     大家都知道C++是一们计算机语言,这一点也没错,但是你知道C++里面还包含了另外一种子语言么?呵呵,恐怕知道的人就不多了,会用的人就更少了。但是既然经过了这么多年的发展,C++语言里面出现了这种子语言(模板)自然有它的根源的。
  
  为什么说C++模板是一种语言呢?
  
  为了回答这个问题,首先需要考虑一下什么是计算机语言,关于这个精确的定义,很多的计算机基础教程上都有,这里给出一种比较窄的定义:
  能够在计算机上表达选择结构,循环结构,同时能够进行进行整数的四则运算的体系就是一种计算机语言。
  
  很显然,C++自然是一种计算机语言了,还有Basic,Fortran,Pascal等等都是计算机语言。之所以讨论这么多的概念问题是为了说明:如何证明C++的模板语法是一种计算机语言。又因为模板是C++语言的一个元素,所以又可以将C++模板语法称为C++的二级语言或者子语言。在本文中将会通过使用模板分别实现整数四则运算,选择结构以及循环结构来证明C++模板语法构成了一个完整的计算机语言。
  
  另外特别值得注意的是,因为C++的模板语言是在编译器编译的时候完成的,所以又称为静态语言,通常的C++语言又称为动态语言或者运行时语言。正是因为模板语言是在编译期完成的,所以可以借助于这种编译期的计算实现代码自动生成的目的,从而实现C++自动化编程。
  
  首先看看,模板是如何完成编译期四则计算的。

#ifdef CODE1    //编译期四则计算的示例代码
#include
template struct Add { enum{value = i+j}; };
template struct Sub { enum{value = i-j}; };
template struct Mul { enum{value = i*j}; };
template struct Div { enum{value = i/j}; };
int main()
{
        std::cout << "4+2=" << Add<4,2>::value << std::endl;
        std::cout << "4-2=" << Sub<4,2>::value << std::endl;
        std::cout << "4*2=" << Mul<4,2>::value << std::endl;
        std::cout << "4/2=" << Div<4,2>::value << std::endl;
        //为了证明上面的计算是在编译期进行的,编写下面的代码测试
        //将模板值作为数组定义时使用的参数就可以证明是在编译期执行的计算:}
        int a[Add<4,2>::value];//这么定义并没有错
        int b[Sub<4,2>::value];
        int c[Mul<4,2>::value];
        int d[Div<4,2>::value];
        std::cout << sizeof(a)/sizeof(int) << std::endl;
        std::cout << sizeof(b)/sizeof(int) << std::endl;
        std::cout << sizeof(c)/sizeof(int) << std::endl;
        std::cout << sizeof(d)/sizeof(int) << std::endl;
        return 0;
}
#endif//CODE1
////////////////////////////////////////////////////////////////////////////////
//程序运行结果如下所示:
/*******************************************************************************
4+2=6
4-2=2
4*2=8
4/2=2
6
2
8
2
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

    从代码CODE1中可以看出使用整型模板参数的模板是可以实现编译期计算的,证明了这个计算过程是在编译期完成的。

   现在看看如何使用C++模板实现选择结构,见代码CODE2:

#ifdef CODE2    //编译期实现选择的示例代码
#include
template struct IF
{
        typedef Then result;//将Then类型作为条件为真的返回值(返回值为类型)
};
template    struct IF
{
        typedef Else result;//将Else类型作为条件为假的返回值(返回值为类型)
};
//为了测试这个IF选择结构,需要下面的两个类型定义:
struct True {static void Print(){std::cout << "真" << std::endl;}};
struct False{static void Print(){std::cout << "假" << std::endl;}};
int main()
{
        IF<1==1,True,False>::result::Print();
        IF<1!=1,True,False>::result::Print();
        return 0;
}
#endif//CODE2
////////////////////////////////////////////////////////////////////////////////
//程序运行结果如下所示:
/*******************************************************************************


*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

    从CODE2中可以看出,这里操作的对象是类型,而CODE1中的操作对象是整数,到了这
里可以总结如下:C++模板元编程中的操作对象只有两种,一种是整形数,包括bool,char
,int,long,(signed unsigned)都可以,它们都可以当作整数使用,赋值和保存结果的
方式都是通过枚举变量来实现;另一种就是类型了,赋值和保存结果都是通过typedef来实
现的。例如CODE2中将IF的选择结果以Result的方式保存作为结果就是通过typedef实现的。

    再来看看循环结构:

#ifdef CODE3    //编译期实现循环的示例代码
#include
//为了简单采用一个阶乘作为例子,因为如果用普通的C++语法来实现阶乘函数的话需要
//一个循环结构的,这里采用模板递归的方式实现了这种阶乘,也就实现了一种特殊的
//循环结构。
template struct Power
{
        enum{value=n*Power::value}; //循环递归过程
};
template<> struct Power<0>
{
        enum{value=1}; //0的阶乘是1,也是循环的终止条件
};
int main()
{
        int a[Power<5>::value];//同样用数组参数来判断是否在编译期完成计算
        std::cout << sizeof(a)/sizeof(int) << std::endl;
        return 0;
}
#endif//CODE3
////////////////////////////////////////////////////////////////////////////////
//程序运行结果如下所示:
/*******************************************************************************
120
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

    从CODE3中我们可以看出Power是通过模板递归的方式实现循环的,而且这个循环过程
是在编译期完成的。到了这里可以总结出:C++模板元编程中实现循环的方式只有一种,那
就是模板递归实现循环。虽然这里的Power的循环不怎么直接,但是它确确实实是一个循环
结构,只不过是一个非常特殊的循环结构。实际上采用模板递归的方法可以实现普通C++语
法里面的for循环,while循环,do-while循环这些通用的循环结构。

    到目前为止,已经成功的证明了C++模板是一个完整的计算机语言。既然是一门语言,
当然可以做许许多多的事情,这就在于每个人的发挥了。最后给出一个通用的LOOP循环,
这个LOOP循环可以进行简单的循环算法设计了,下面的例子中将会说明这一点:

#ifdef CODE4
#include
template void print()
{//这里的n是编译期的结果,可以用来定义数组的
        int a[n+1];//这么做是为了证明n是编译期常量,同时避免出现零个元素的数组
        std::cout << sizeof(a)/sizeof(int)-1 << " " ;
}
template struct LOOP
{
        static void execute(){LOOP::execute();print();}
};
template <>struct LOOP<0>//循环终止条件
{
        static void execute(){print<0>();}
};
int main()
{
        LOOP<5>::execute();
        return 0;
}
#endif//CODE4
////////////////////////////////////////////////////////////////////////////////
//程序运行结果如下所示:
/*******************************************************************************
0 1 2 3 4 5
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

    从CODE4中可以看出,这个静态LOOP循环是一个相对来说通用的循环代码,只需要将自
己的功能代码写入到一个函数(print)中就可以实现静态循环了,更重要的是,这个静态
LOOP循环实现了静态代码和动态代码的连接,因此用途更加广泛,主要可以用来产生代码。

 

你可能感兴趣的:(编程,C++,struct,语言,pascal,fortran)