C++自动化(模板元)编程基础与应用(5)

#if 0

在上一篇文章里面讨论了C++里面的代码生成技术,使用的是scatter,不过上一篇文
章里面也提到了,前一篇文章里面讨论的代码生成模板scatter使用的类型串绝对不允许
重复。其实上一篇中的scatter使用由重复的类型的类型串也是能够正常生成代码的,不
过产生的代码却不能将类型重复的变量分辨出来,这样生成的代码就没有了什么实际意义
,所以在这一章中将要解决的问题是:重新编写一个可以使用重复类型的类型串生成代码
,并且能够采用一定的方法将这些生成的变量分辨出来。

那么该如何编写这里需要的代码呢?上一章里面的scatter见下面的代码:

#endif
#ifdef CODE_NOTE
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>
{
};
#endif//CODE_NOTE
#if 0

虽然上面的代码生成机制生成的重复类型的代码不能够通过静态转型(static_cast)分
辨出来,但是上面的代码却给出另外一种重要的思想:使用不含有重复类型的类型串采用
上面的代码生成技术生成的代码却可以使用静态转型(static_cast)分辨出来。前一章里面
的例子都采用了这种思想。那么现在我们可不可以同样使用这种思想编写出一个可以使用
重复类型的类型串生成代码,并且能够通过静态转型(static_cast)方法将这些生成的变量
分辨出来呢?答案是肯定的,在这里同样是采用前面所讨论的多加一层包裹的方法来实现。

我们知道对于下面的模板类:

#endif
#ifdef CODE_NOTE
template <size_t>
struct Struct
{
};
Struct<0> a;
Struct<1> b;
Struct<2> c;
Struct<3> d;
//... ...
#endif//CODE_NOTE
#if 0

上面的Struct模板的模板参数不同将会生成不同的类型。例如:上面的Struct<0>、
Struct<1>、Struct<2>和Struct<3>是四种不同的类型。这一点就像是给这个模板编号让这
个编号的不同来区分出不同的类型。正是因为这种现象的存在我们才有了这样的思想:在
新的scatter代码生成机制中给每一个串中的类型声明变量的时候额外添加一个类型索引号
。这样就可以使用静态转型方法分辨出同类型的变量了。见代码CODE1所示:

#endif
#ifdef CODE1
#include <iostream>
#include "meta.h"//为了引入pandaxcl::cons
//下面的代码仅仅是为了测试产生代码的索引号和类型是否匹配而引入的特性类模板
//说得简单点,这里所谓的特性类就是一种大型的switch,case结构,只不过是跟据
//类型的不同由编译器来自动选择相应的模板。在这里讨论的特性类实际上可以应用
//到撤销和重做框架的序列化方案中去,当然这是为了保存类型名称了。
template <class T> struct traits;
template <> struct traits<char>{static const char*name(){return "char";}};
template <> struct traits<int >{static const char*name(){return "int ";}};

//下面的这个产生代码的格式还可以使用索引号得到基元对象注意了:下面的递归模板的
//终结条件并不是第一个模板参数size_t而是第二个模板参数T,这一点很重要,因为前面
//的文章中讨论的都是以数字0作为终结条件的。所以这里需要特别说明一下,另外也可以
//给你一点灵感:)
template<size_t i,class T,template<class>class Unit>
struct scatter_helper : public Unit<T>
{
//下面的构造函数仅仅是为了输出索引号对应的类型信息而引入的
scatter_helper()
{
std::cout << traits<T>::name() << " : " << i << std::endl;
}
};
template<size_t i,class H,class T,template<class>class Unit>
struct scatter_helper<i,pandaxcl::cons<H,T>,Unit>
: public scatter_helper<i,H,Unit>
, public scatter_helper<i+1,T,Unit>//递增的为每一个类型添加一个额外的索引号
{
typedef pandaxcl::cons<H,T> cons_type;
};
//下面的null_type参看前一章中的代码
template<size_t i,template<class>class Unit>
struct scatter_helper<i,pandaxcl::null_type,Unit>
{
};
//为了和前面章节中讨论的scatter兼容也是为了方便使用,这里重新对scatter_helper进行
//包装生成了一个模板类scatter,这样前面使用的任何方法针对于这个新的scatter类同样
//适用。
template <class Cons,template<class>class Unit>
struct scatter:public scatter_helper<0,Cons,Unit>
{
typedef Cons cons_type;
};
//下面的函数用来根据类型索引号来得到相应的基元类型
template <size_t i,class Cons,template<class>class Unit>
scatter_helper<i,typename pandaxcl::type<Cons,i>::result,Unit>&
field(scatter<Cons,Unit>&obj)
{
typedef typename pandaxcl::type<Cons,i>::result CT;
typedef scatter_helper<i,CT,Unit> RT;
return static_cast<RT&>(obj);
};
template <size_t i,class Cons,template<class>class Unit>
const scatter_helper<i,typename pandaxcl::type<Cons,i>::result,Unit>&
field(const scatter<Cons,Unit>&obj)
{
typedef typename pandaxcl::type<Cons,i>::result CT;
typedef scatter_helper<i,CT,Unit> RT;
return static_cast<const RT&>(obj);
};
//
//下面是测试代码
namespace xcl=pandaxcl;
template <class T> struct TestUnit
{
T _value;
};
int main()
{
typedef xcl::cons<int,
xcl::cons<char,
xcl::cons<char,
xcl::cons<int,
xcl::null_type> > > >CONS;
std::cout << "========scatter_helper========" <<std::endl;
{
scatter_helper<0,CONS,TestUnit> v;
static_cast<scatter_helper<0,int ,TestUnit>&>(v)._value = 10;
static_cast<scatter_helper<1,char,TestUnit>&>(v)._value = 'B';
static_cast<scatter_helper<2,char,TestUnit>&>(v)._value = 'C';
static_cast<scatter_helper<3,int ,TestUnit>&>(v)._value = 11;
std::cout << static_cast<scatter_helper<0,int ,TestUnit>&>(v)._value << " ";
std::cout << static_cast<scatter_helper<1,char,TestUnit>&>(v)._value << " ";
std::cout << static_cast<scatter_helper<2,char,TestUnit>&>(v)._value << " ";
std::cout << static_cast<scatter_helper<3,int ,TestUnit>&>(v)._value << " ";
}
std::cout << std::endl << "========field(scatter&)=======" <<std::endl;

{
scatter<CONS,TestUnit> v;
field<0>(v)._value = 20;
field<1>(v)._value = 'F';
field<2>(v)._value = 'G';
field<3>(v)._value = 21;
std::cout << field<0>(v)._value << " ";
std::cout << field<1>(v)._value << " ";
std::cout << field<2>(v)._value << " ";
std::cout << field<3>(v)._value << " ";
}
std::cout << std::endl << "=====field(const scatter&)====" <<std::endl;
{
scatter<CONS,TestUnit> v;
field<0>(v)._value = 30;
field<1>(v)._value = 'J';
field<2>(v)._value = 'K';
field<3>(v)._value = 31;
//测试常量情况下的field辅助函数
const scatter<CONS,TestUnit>&cv = v;
std::cout << field<0>(cv)._value << " ";
std::cout << field<1>(cv)._value << " ";
std::cout << field<2>(cv)._value << " ";
std::cout << field<3>(cv)._value << " ";
}
std::cout << std::endl << "==============================" <<std::endl;
return 0;
}
#endif//CODE1

//该程序运行结果如下:
/*******************************************************************************
========scatter_helper========
int : 0
char : 1
char : 2
int : 3
10 B C 11
========field(scatter&)=======
int : 0
char : 1
char : 2
int : 3
20 F G 21
=====field(const scatter&)====
int : 0
char : 1
char : 2
int : 3
30 J K 31
==============================
*******************************************************************************/

#if 0

从运行结果可以看出我们已经成功的解决了本文开头所提出的问题。这个新的代码产生
模板已经写出来了。为了以后使用的方便需要将这个模板类加入到meta.h中。不过本文中使
用的meta.h并没有包含这里的scatter模板类,见附录所示。

本章完。

实际上C++模板元编程的基础与应用中的基础篇已经写完了,从下一章开始将会讨论这种
编程技术的一些应用专题。下一章里面将会涉及到的专题是类型特性trait。(敬请关注!)

未完,待续...

#endif
#ifdef CODE_NOTE//附录:本文采用的meta.h文件内容如下:
#pragma once
namespace pandaxcl{
//
template <bool Condition,class Then,class Else>
struct IF
{
typedef Then result;//将Then类型作为条件为真的返回值(返回值为类型)
};
template<class Then,class Else>
struct IF<false,Then,Else>
{
typedef Else result;//将Else类型作为条件为假的返回值(返回值为类型)
};
//
//
加入一个外覆层来传递额外的模板参数
template <template<size_t>class Function,size_t start,size_t finish,size_t step>
struct LOOP
{
//为了能够正确的计算出实际的循环终止变量,需要对给定的终止变量
//进行计算,以满足正确的循环语义
enum{real_finish=(finish/step*step+start)};
static void execute()
{
LOOP_BODY<real_finish,true>::execute();
}
//下面的这个模板函数是为了能够实现静态代码和动态代码连接
template <class EnvironmentType>
static void execute(EnvironmentType&e)
{
LOOP_BODY<real_finish,true>::execute(e);
}
private:
//引入了一个布尔型的模板参数用来确定循环的终止条件
template <size_t i,bool> struct LOOP_BODY
{
static void execute()
{
LOOP_BODY<i-step,(i-step>start)>::execute();
Function<i-step>::execute();
}
//下面的这个模板函数是为了能够实现静态代码和动态代码连接
template <class EnvironmentType>
static void execute(EnvironmentType&e)
{
LOOP_BODY<i-step,(i-step>start)>::execute(e);
Function<i-step>::execute(e);
}
};
//循环的终止语句,停止递归以结束循环
template <size_t i> struct LOOP_BODY<i,false>
{
static void execute(){}
//下面的这个模板函数是为了能够实现静态代码和动态代码连接
template <class EnvironmentType>
static void execute(EnvironmentType&e){}
};
};
//为了模板化必须将原来的输出函数做成一个模板结构体
//template<size_t i> struct Function
//{
// static void execute()
// {
// //你的代码在这里编写
// }
//};
//
//
//cons的实现,采用和STL类似的类型命名方式
template <class FirstType,class SecondType>
struct cons
{
typedef FirstType first_type;
typedef SecondType second_type;
};
struct null_type;//类型串终结符
//下面是两个为了实现静态类型循环所需要的静态元函数
//length元函数的实现
template<class Type>struct length;
template<>struct length<null_type>
{//返回值为整数,命名为value
enum{value=0};
};
template<class FirstType,class SecondType>
struct length<cons<FirstType,SecondType> >
{//返回值为整数,命名为value
enum{value=1+length<SecondType>::value};
};
//type元函数的实现
template<class Cons,size_t index>struct type;
template<class FirstType,class SecondType>
struct type<cons<FirstType,SecondType>,0>
{//返回值为类型,命名为result
typedef FirstType result;
};
template<class FirstType,class SecondType,size_t i>
struct type<cons<FirstType,SecondType>,i>
{//返回值为类型,命名为result
typedef typename type<SecondType,i-1>::result result;
};
//index元函数根据类型得到类型串中该类型位置
template<class Cons,class Test>struct index;
template<class Test> struct index<null_type,Test>
{
enum{value=-1};
};
template<class T,class Test> struct index<cons<Test,T>,Test>
{
enum{value=0};
};
template<class H,class T,class Test> struct index<cons<H,T>,Test>
{
private:
enum{temp=index<T,Test>::value};
public:
enum{value=(temp==-1?-1:1+temp)};
};
//
//下面是实现代码自动生成的模板元函数,主要参考了Loki的代码
//为了撤销和重做库的独立性,将该功能从Loki库中提取出来
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;
};
//下面的null_type参看前一章中的代码
template<template<class>class Unit>
struct scatter<null_type,Unit>
{
};
//
}//namespace pandaxcl{
#enidf//CODE_NOTE
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值