By Z.H. Fu
https://fuzihaofzh.github.io/blog/
## C++类型推导
用过C++11的同学一定对里面的auto和decltype映像深刻,auto常用于申明变量的自动推导。例如:
1 2
| auto c = a + b; decltype(a + b) c = a + b;
|
如果a、b都是int型,那么c自动为int型;如果a、b都是double型,那么c自动为double型。但是,如果c是一个模板的类型,模板里面的东西往往很长,如果不使用auto的话,将要写很多的东西。而且在设计模板的时候,如果涉及两个class操作得出第三个class,则更加无法事先指定类型。然而,很多公司的编译器过于古老,本文探讨了一种auto/decltype的近似实现方式(boost的typeof)。
## boost typeof
这个想法非常trick,因为我们要在编译期决定其类型,而sizeof是在编译期执行的,我们可以利用这个特性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| template<size_t> struct TypeId;
#define REGISTER_TYPE(T, id) \ template<> struct TypeId<id> { \ char value[id]; \ typedef T type; \ static char const* const name; \ }; \ char const* const TypeId<id>::name = BOOST_PP_STRINGIZE(T); \ TypeId<id> type_to_id(T);
#define TYPEID_(value) TypeId<sizeof(type_to_id(value))> #define TYPEOF(value) typename TYPEID_(value)::type #define TYPENAME(value) TYPEID_(value)::name
REGISTER_TYPE(int, 1) REGISTER_TYPE(unsigned int, 2)
int main() { int x; TYPEOF(x) y; std::cout << TYPENAME(y) << '\n'; }
|
其中,REGISTER_TYPE是注册宏,对每个type偏特化一个struct,每个struct里面包含一个id长度的value数组;type_to_id是一个用宏定义的一系列重载函数,输入类型为T,返回值为TypeId
的结构体,在执行TYPEOF的时候,type_to_id(value)只会在编译期做类型推导,根据value的类型,选择合适的type_to_id重载,进而从函数返回类型中得到相应的type。当然C++11以后可以直接用decltype,c++11以前可以用__decltype也可实现相应的功能。
参考文献
[1] http://stackoverflow.com/questions/12199280/how-to-implement-boost-typeof