兔子的技术博客

兔子

   :: 首页 :: 联系 :: 聚合  :: 管理
  202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

留言簿(10)

最新评论

阅读排行榜

评论排行榜

boost的typeof 试探

皮贝贝 posted @ 2009年11月27日 05:26 in boost with tags boost typeof , 541 阅读

前段时间在 csdn 上发了帖子讨论过这个问题,当时讨论了有些地方还是不懂。今天又看了下源码,写下来备忘:(研究 MSVC 的部分)

先看  BOOST_TYPEOF 的主要计算流程:

 

1
2
# define BOOST_TYPEOF(expr) \
    boost::type_of::msvc_typeid_wrapper< typeid(boost::type_of::encode_start(expr)) >::type

 

这里主要有三个步骤:

 1. encode_start( expr )。这一步会将 expr 的类型注册, 会形成一个签名的模板类: msvc_typeid_wrapper <typeid(expr)> 类, expr 的 type 就存储在这个类中。

 2.  typeid ( $(1) )。 这一步将第一步计算出的 type 结果(注意,这个结果是函数 encode_start() 返回的,不能直接拿来作类型用)再做 typeid 计算, 生成一个 type_info 对象

 3. msvc_typeid_wrapper< $(3) >。这一步会通过第二部计算出的 type_info 对象来找到注册的对应的 type。完毕。

encode_start

这是个无实作的模板函数,主要完成下列功能:

1. 如果参数的类型没有注册,注册之

2. 返回这个注册的类型

函数的源码:

 

1
2
3
4
5
6
7
template<typename T> typename disable_if<
    typename is_function<T>::type,
    typename encode_type<T>::input_type>::type encode_start(T const&);
 
template<typename T> typename enable_if<
    typename is_function<T>::type,
    typename encode_type<T>::input_type>::type encode_start(T&);

 

 

暂且不管 is_function.

这个函数主要通过模板类 encode_type 来完成具体功能(两步都有具体的对应语句):

 

1
2
3
4
5
6
7
8
9
10
11
        template<typename T>
        struct encode_type
        {
            typedef encode_type<T> input_type;
            //
            // 1步. 类型注册
            typedef typename msvc_register_type<input_type,msvc_typeid_wrapper<typeid(input_type)> >::id2type registered_type;
 
            // 2步. 返回注册好的类型
            typedef T type;
        };

 

 

类型注册是通过模板类 msvc_register_type 来完成注册,有两个参数,一个是 encode_type 要注册的类型, 注册成另一个参数 msvc_typeid_wrapper, 这样会形成一个 签名为 typeid(encode_type) 的 msvc_typeid_wrapper 签名模板类( 这个模板类中存储有 type )。

至此,形成了一个模板类签名,注册成功了。这里我们知道了 以后就是通过 msvc_typeid_wrapper 类来找到 typeid(expr ) 对应的 type的。

具体注册过程,就更简单了:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename ID>
 struct msvc_extract_type
 {
     struct id2type;
 };
 
 template<typename T, typename ID>
 struct msvc_register_type : msvc_extract_type<ID>
 {
     typedef msvc_extract_type<ID> base_type;
     struct base_type::id2type // This uses nice VC6.5 and VC7.1 bugfeature
     {
         typedef T type;
     };
 };

 

 

看,就是通过模板的特化来实现的,这是模板的最普遍、最常用的技法。

 

msvc_typeid_wrapper

msvc_typeid_wrapper< typeid(...) >

这个类现在可以看成一个映射集合了,通过 typeid 能找到对应的注册的 type。之所以可以看成映射集合,主要还是 模板的特化起的效果,因为在找类型type之前就完成了模板的特化动作,注册完毕。

msvc_typeid_wrapper 的模板类很简单:

 

1
2
3
4
5
6
7
8
9
10
        template<const std::type_info& ref_type_info>
        struct msvc_typeid_wrapper {
            // 第一步 找到对应的 id2type
            typedef typename msvc_extract_type<msvc_typeid_wrapper>::id2type id2type;
             
            // 第二步 获取 id2type 中的 具体 msvc_typeid_wrapper 签名模板类
            typedef typename id2type::type wrapped_type;
            // 第三步 从签名类中取得要类型
            typedef typename wrapped_type::type type;
        };

 

 

模板类的参数是 type_info , 这个 type_info 可以作为编译器量参与计算,这点很关键。

 

typeid

 

typeid也和 sizeof一样在编译期完成计算, 返回 一个 type_info 对象, 这个对象是唯一的。

我以前不知道的是这个 typeid 返回的对象可以作为模板类的参数,牢记。

posted on 2011-08-29 09:22 会飞的兔子 阅读(1025) 评论(0)  编辑 收藏 引用 所属分类: C++库,组件

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理