现在的位置: 首页 > 综合 > 正文

自动化C++程序设计

2013年10月18日 ⁄ 综合 ⁄ 共 6249字 ⁄ 字号 评论关闭
#if 0

在通常的编程问题中经常会遇到使用宏的情况,但是在很多的情况下C宏又非常的不方
便,在自动化编程方面,使用宏就非常不方便了,甚至不可能了,下面我们将要考虑一个C
宏不可以做到的事情如何使用模板元编程来实现。在本文中将会以一个具体的例子展示这
种自动化方法,希望能够起到抛砖引玉的效果:)

首先考虑下面的问题,有下面的一个类Class,有几个基类成员;需要写一个函数
print来输出所有的基类成员的内容:

#endif

#ifdef CODE_NOTE
class Class
:public std::vector<int>
,public std::vector<float>
{
public:
void print();
};
#endif//CODE_NOTE

#if 0

采用宏的方案可以很容易的实现这个print函数;具体方案如下:

#endif

#ifdef CODE_NOTE
void Class::print()
{
#define PRINT(T){/
typedef std::vector<T> VT;/
VT&v=static_cast<VT&>(*this);/
std::copy(v.begin(),v.end(),std::ostream_iterator<T>(std::cout," "));/
std::cout << std::endl;}
PRINT(int)
PRINT(float)
#undef PRINT
}
#endif//CODE_NOTE

#if 0

那么如果基类成员的数量增多以后,例如:下面的这种形式,类型增加到了5个:

#endif

#ifdef CODE_NOTE
class Class
:public std::vector<int>
,public std::vector<float>
,public std::vector<double>
,public std::vector<char>
,public std::vector<long>
{
public:
void print();
};
#endif//CODE_NOTE

#if 0

当然可以采用前面的只有两个类型的情况一样将PRINT宏多复制几遍,修改相应的类型
就可以啦,如下所示:

#endif

#ifdef CODE_NOTE
void Class::print()
{
#define PRINT(T){/
typedef std::vector<T> VT;/
VT&v=static_cast<VT&>(*this);/
std::copy(v.begin(),v.end(),std::ostream_iterator<T>(std::cout," "));/
std::cout << std::endl;}
PRINT(int)
PRINT(float)
PRINT(double)
PRINT(char)
PRINT(long)
#undef PRINT
}
#endif//CODE_NOTE

#if 0

但是我们注意到了这里明摆着是重复性的工作,一个不小心还很容易漏写造成不必要的
麻烦。

我们看看上面的实现方式有些什么问题:一方面要修改类的头部,另一方面也要复制
很多结构非常雷同的代码(PRINT宏),这就是采用C宏实现的弊端,更严重的是,由于针对
不同的类型数量需要修改print函数体,这样,这里的Class类就不能够以库的形式提供,
因为作为库的代码不应该让用户随便修改的。那么当真正遇到这里的问题,数量增加到了5
个,C宏实现仅仅是一些固定的规则:将PRINT宏针对不同的类型复制多遍,这个手工过程
完全可以用本文后面的代码来实现,同时又没有这里使用宏实现不能以库代码的形式提供
的弊端了,因而,后面的示例代码是完全可以以库的形式提供的。

#endif

#if CODE1
////////////////////////////////////////////////////////////////////////////////
//静态选择结构,名称就可以很明白的表达意思了
template<bool,class T,class F>struct IF
{
typedef T result;
};
template<class T,class F>struct IF<false,T,F>
{
typedef F result;
};
//静态FOR循环结构的实现,FOR循环的结束语句
struct STOP
{
template<class E> static void execute(E&e){}
};
//FOR循环的循环条件结构
struct LESS { template<int x,int y> struct code{enum{value = (x < y)};}; };
//FOR循环结构实现
template<int from,class ConditionType,int to,int step,class StatementType>struct FOR
{
//真正的循环过程在这个函数里面,理解下面的过程将是理解整篇文章的关键
//实际上这里采用的是模板递归实现的循环过程。
template<class EnvironmentType>
static void execute(EnvironmentType&e)
{
//执行本条语句
IF<ConditionType::template code<from,to>::value
,typename StatementType::template code<from>
,STOP>::result::execute(e);
//执行本条语句的下一条语句
IF<ConditionType::template code<from,to>::value
,FOR<from+step,ConditionType,to,step,StatementType>
,STOP>::result::execute(e);
}
};
//////////////////////////////////////////////////////////////////
//为了能够在其它的环境下也能构方便的编译运行该程序,我将Loki里面的
//typelist概念重新表述为cons,这样一方面可以出去Loki中的Typelist的神秘面纱
//另一方面也是因为这段代码比较简单
struct null_type;//类型列表的尾部元素表示类型已经结束了
template<class H,class T>
struct cons
{
typedef H head_type;
typedef T tail_type;
};
//计算类型列表的长度的元函数
template<class T>struct length;
template<>struct length<null_type>
{
enum{value=0};
};
template<class H,class T>struct length<cons<H,T> >
{
enum{value=1+length<T>::value};
};
//根据索引得到相应索引值类型的元函数
template<class Cons,unsigned int index>struct type;
template<class H,class T>struct type<cons<H,T>,0>
{
typedef H result;
};
template<class H,class T,unsigned int i>struct type<cons<H,T>,i>
{
typedef typename type<T,i-1>::result result;
};
////////////////////////////////////////////////////////////////////////////////
//下面是产生代码的元函数,相当于Loki里面的GenScatterHierarchy结构
template<class T,template<class>class Unit>
struct scatter : public Unit<T>
{
};
template<class H,class T,template<class>class Unit>
struct scatter<cons<H,T>,Unit>
: public scatter<H,Unit>
, public scatter<T,Unit>
{
typedef cons<H,T> cons_type;
};
template<template<class>class Unit>
struct scatter<null_type,Unit>
{
};
////////////////////////////////////////////////////////////////////////////////
//下面是测试代码
#include <iostream>
#include <iterator>
#include <vector>
//仅仅为了兼容scatter产生代码的接口而追加一层代码
template<class T> struct VectorUnit:public std::vector<T>{};
template <class Cons>
class Class : public scatter<Cons,VectorUnit>
{
public:
typedef Cons cons_type;//类型列表类型
struct PRINT{//用于输出用的静态循环环境
struct Environment//环境变量
{
Environment(Class&ref):_ref(ref){}
Class&_ref;
};
struct Statement//静态循环语句
{
template<int i>struct code//语句代码
{
template<class E>
static void execute(E&e)
{
//Your code here
typedef typename type<cons_type,i>::result CT;
VectorUnit<CT>&v = static_cast<VectorUnit<CT>&>(e._ref);
std::copy(v.begin(),v.end(),std::ostream_iterator<CT>(std::cout," "));
std::cout << std::endl;
}
};
};
};
//下面就是使用静态循环代码实现的类型循环语句
void print()
{
typename PRINT::Environment e(*this);//每一个循环都需要使用的环境变量
//下面的这行代码就相当于很多的宏替换了,但是这行代码就可以使这个类以库的形式提供了
FOR<0,LESS,length<cons_type>::value,+1,typename PRINT::Statement>::execute(e);
}
};
int main()
{
//给出5个类型的类型列表
typedef cons<int,
cons<short,
cons<long,
cons<float,
cons<double,
null_type> > > > > CONS;
//用这个类型列表调用Class模板生成一个具体类CLASS
typedef Class<CONS> CLASS;
//定义一个这样的具体类的一个变量
CLASS cls;
//初始化类变量cls中的数据
static_cast<VectorUnit<int>&>(cls).push_back(1);
static_cast<VectorUnit<int>&>(cls).push_back(2);
static_cast<VectorUnit<int>&>(cls).push_back(3);
static_cast<VectorUnit<int>&>(cls).push_back(4);

static_cast<VectorUnit<short>&>(cls).push_back(4);
static_cast<VectorUnit<short>&>(cls).push_back(3);
static_cast<VectorUnit<short>&>(cls).push_back(2);
static_cast<VectorUnit<short>&>(cls).push_back(1);

static_cast<VectorUnit<long>&>(cls).push_back(10);
static_cast<VectorUnit<long>&>(cls).push_back(20);
static_cast<VectorUnit<long>&>(cls).push_back(30);
static_cast<VectorUnit<long>&>(cls).push_back(40);

static_cast<VectorUnit<float>&>(cls).push_back(1.1);
static_cast<VectorUnit<float>&>(cls).push_back(2.2);
static_cast<VectorUnit<float>&>(cls).push_back(3.3);
static_cast<VectorUnit<float>&>(cls).push_back(4.4);

static_cast<VectorUnit<double>&>(cls).push_back(4.4);
static_cast<VectorUnit<double>&>(cls).push_back(3.3);
static_cast<VectorUnit<double>&>(cls).push_back(2.2);
static_cast<VectorUnit<double>&>(cls).push_back(1.1);
//现在就可以利用前面的静态循环print函数输出结果了
cls.print();
return 0;
}
#endif//CODE1
////////////////////////////////////////////////////////////////////////////////
//该程序的运行结果如下:
/*******************************************************************************
1 2 3 4
4 3 2 1
10 20 30 40
1.1 2.2 3.3 4.4
4.4 3.3 2.2 1.1
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

#if 0

从上面的代码很容易看出本来不能够以库的形式提供的代码,现在可以以库的形式提
供了。这是C宏根本不可能实现的啊:)。做到了这里,你可能有很多的想想法,这正是我写
这篇文档所希望达到的效果。如果觉得这篇文章还不错,请发点评论,不管是好还是不好
你的评论将会鼓励我写出更多更好的文章出来,因为你让我知道了我写的文章是有人关
注的:)

在我的博客里面已经有了“C++自动化(模板元)编程基础与应用”系列的文档,敬请
关注!

#endif

抱歉!评论已关闭.