C++ 下 typeof auto

来源:互联网 发布:js 有没有trim函数 编辑:程序博客网 时间:2024/04/28 13:48

现在我们有这样一坨代码:

C++11下有typeof和auto关键字,于是像上面第3行那样纠结的位置可以变得简单不少:

假如有typeof的话,auto可以很简单的模拟出来,那么问题的关键点在于如何实现typeof。


一、需要注册id的typeof

在C++里,可以在编译期计算表达式类型的只有下面两个东西:

1. sizeof
    这东西很强大,不论后面的表达式是什么,均可以在编译期正确得到类型并直接返回类型大小。
2. typeid
    若不使用C++的RTTI功能,typeid会在编译期计算出表达式的类型,并返回一个type_info引用。

使用第一种方法,我们可以得到一个数字,只要这个数字对类型而言是唯一的,那么我们就可以通过它反向得到类型。
类似这样写:

第6-9行定义了假函数encode,负责把__VA_ARGS__的类型取出来。sizeof运算符保证了encode并不会真正被执行到。

为了让我们前面的代码可以工作,还需要使用模板特化的机制注册一些类型:


二、自动分配id的typeof

目前我们实现的type_of虽然可以工作,但在干活之前必须要先注册一大堆类型,而且还需要给每个类型分配一个唯一的id。没有注册的类型是无法动态推导的。
boost里使用了mpl库里的一些东西,完成了REGISTER_TYPE的过程,自动化的给每个放入BOOST_TYPE_OF里的类型分配了唯一的id。我们手头上没有这么NX的东西,只好使用一些轻量级的玩意了。

比如上面提到的typeid,就是个不错的id生成器,也具有sizeof类似的功能。
虽然多态类继承的情况会让typeid在编译期失效,但只限于传入对象的情况。我们可以使用指针规避这个问题,typeid将在编译期返回一个指针类型的type_info。

下面我们开始实作可以自动分配id的typeof。首先,我们需要一个可以把type_info&变成类型的玩意:

最后把类型解出来:

使用Encode、Decode的目的,是为了绕过typeid对对象可能进行的运行时处理。

不要妄想C++的模板自动推导可以这样写:

为了让Extract能够认得传入的类型信息,我们得注册我们的类型,但是不再需要传入id了:


三、全自动的typeof

虽然仅仅写一行REGISTER_TYPE已经不是什么大问题了,但多写这一行还是一个让人不爽的事情。
想要实现全自动注册,得解决一个麻烦的问题:如何通过const type_info&特化模板?

幸好vc里还有一些小花招可以利用,我们可以尝试在一个类的内部特化一个类模板:

这样我们就可以写出一个专门用于注册的类模板:

[cpp] view plaincopy
  1. /* 
  2.     Register a type 
  3. */  
  4.   
  5. template<typename T, typename ID>  
  6. struct Register : Extract<ID, T>  
  7. {  
  8.     typedef typename id2type<true>::type_t type_t;  
  9. };  

它将通过继承的Extract自动特化出一个存有类型信息的id2type。

后面的事情就简单了,只需要稍微改写一下Encode:

扫尾工作:

区别对待vc和gcc,并定义auto:

0 0
原创粉丝点击