C++自动类型推导

C++自动类型推导

By Z.H. Fu

切问录 www.fuzihao.org

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