注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

为着理想勇敢前进

 
 
 

日志

 
 

Boost.Typeof实现分析  

2007-04-13 21:39:11|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
typeof的功能是获取一个表达式的类型,实现的问题在哪里呢?问题就在于需要获取的是一个静态的类型,我们可以用typedef从一个类型找到另外一个类型,可以用模板从一个类型运算出另一个结果,但是归根到底还是需要用别的类型作为模板参数。然而,我们面临的问题是,起始条件只有表达式,这个表达式不是常数,问题的关键就是获取跟表达式类型有关联的一个常数,然后再把这个常数作为模板参数,算出相对应的类型,而这一切都是在编译时做的。

昨天说到,用sizeof和enum可以把一个表达式变成常数。sizeof的参数可以是一个表达式这是不言而喻的,而enum也可以,至少在VC8上可以:
class A { enum{ E = 123 }; };
template<int N> struct X{};
int main() {
  A a;
  X<a.E> x1;
  X<sizeof(a)> x2;
}
以上代码,我们从一个变量a入手,以X<a.E>变成了一个类型,两种做法分别是从enum和sizeof着手。

如果你够聪明的话,你已经能想到typeof应该怎么实现了,但是也许你仍有些疑惑,A的类型和最终得到的X<a.E>或者X<sizeof(a)>是完全不同的类型,这没有意义啊。其实这很容易做到有意义,请看:

template<int N>class A { enum{ E = N }; };
template<int> struct X;


template<> struct X<1>{typedef double type;};
A<1> c(double);

template<> struct X<2>{typedef char type;};
A<2> c(char);

int main()
{
  double a;
  X<c(a).E>::type aa;
  char b;
  X<c(b).E>::type bb;
}

现在,通过一串表达式,我们从一个变量a或者b着手,找回了他们的类型,当然,这需要事先定义他们对应的ID。c(a)这里通过编译器选择重载函数返回了一个 A<1>的类型,A<1>又具有一个E的枚举成员值为1,最后把X<1>::type得到了double. 只要把注册的代码和找回类型的代码做成宏就适合所有没有模板参数的简单类型了。类似的,昨天的代码表现了如何通过sizeof做到同样的一件事情。
需要注意的是,函数c并没有函数体,我们只是需要利用这个重载函数来提取类型而已。

但是Boost.Typeof远比我今天和昨天演示的代码复杂,为了提取模板类型,它将变量提取出类型的函数定义可能是原理类似这样的:
tempalte<typename T1, typename T2>
A<encode<c(T1).E, c(T2).E> > c(std::vector<T1, T2>);
对于没有模板参数的简单类型,我昨天的代码已经可以解决了,但是对于带参数的类型,想要只对模板注册一次就可以找出复杂的模板嵌套关系,靠静态的一个一个注册每一个具体类型的ID是不现实的,Boost.Typeof把模板嵌套类型进行了编码,默认是输出50个32位整数作为一个类型的ID。而计算一个类型的ID也不是简单的写死,而是用到模板元函数进行编译时的计算,这些计算是基于Boost.MPL的。

这几篇文章,如果第一次涉及模板元编程的领域的人很难看懂,对于精于此道之人又显得太过业余,我想我写这几篇文章能让人真的一下理解模板元编程那是不可能的。所以我想,只要能让读者引起兴趣,在似懂非懂之间进行思考,我的目的就达到了。



  评论这张
 
阅读(420)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018