有的时候可能会需要将整数映射为类型, 看下面这个例子, 假设对于某个类, 如果它是多态的, 我们就调用其clone方法创建一个新对象; 如果它不是多态的, 则直接调用其构造函数. 因此我们需要根据模板参数进行选择.

template <typename T, bool isPolymorphic>
class MyClass {
	void foo() {
		T *pObj = ...;
		if (isPolymophic) {
			T *pNewObj = pObj->clone();
			// do something with pNewObj
		} else {
			T* pNewObj = new T(*pObj);
			// do something with pNewObj
		}
	}
}

这段代码看似没有问题, 但实际隐含了一个前提条件. 要让它编译成功, 那if-else的两个分支必须都能单独编译成功, 虽然模板参数是在编译期就确定的, 编译器完全能够在编译期知道会选择哪一个分支. 那问题就来了, 对不是多态的对象, 我们没有定义clone()方法, 这会导致如果进入了第一个分支(虽然实际上不可能进入), 第一个分支是无法编译成功的!

那如果有办法在处理非多态对象时, 让编译器无视第一个分支就好了.

我们可以利用模板特化配合函数重载来实现这一点

template <int v>
struct int2type {
	enum { value = v };
};

template <typename T, bool isPolymorphic>
class MyClass {
private:
	void foo(T *pObj, int2type<true>) {
		T *pNewObj = pObj->clone();
		// do something with pNewObj
	}
	void foo(T *pObj, int2type<false>) {
		T* pNewObj = new T(*pObj);
		// do something with pNewObj
	}
public:
	void foo() {
		T *pObj = ...;
		foo(pObj, int2type<isPolymorphic>());
	}
}

在这里我们创建了一个int2type结构体, 根据它的模板参数不同里面的枚举值也不同. 调用公共版本的foo()方法时, 由于isPolymorphic是一个编译期常量, 编译器只会根据它特化出来的int2type类型去调用正确的重载版本. 这样就利用函数重载实现了编译期选择, 最终的效果类似于让编译器"无视了"不需要的分支.

当你需要根据不同分支做不同处理, 并且分支条件在编译期就能确定, 而且必须在编译期就选择分支时, 整数映射为类型的技巧就非常有用. 总之, if-elseint2type的区别在于, if-else是运行时分支选择, 要求每个分支都能单独编译成功; 而int2type是编译期分支选择, 可以通过这个技巧让编译器选择性"无视"一些分支.