2.5 型别对型别的映射(Type-to-Type Mapping)
如前所述,不可以对template函数偏特化。如有下面模板函数:
1 template<class T, class U>
2 T* Create(const U& arg)
3 {
4 return new T(arg);
5 }
用来构造一个对象。假设现在有一个widget对象的构造函数需要两个参数,第二个固定为-1。那么你没有办法如下偏特化,如果你写一个CreateWidget()来解决,你将不能在泛型程序中使用。
1 //示意代码,请勿模仿
2 template <class U>
3 widget* Create<widget, U>(const U& arg)
4 {
5 return new widget(arg, -1);
6 }
我们可以通过重载机制来实现,比如传入一个型别为T的形参:
1 template < class T, class U>
2 T* Create(cosnt U& arg, T /* dummy */)
3 {
4 return new T(arg);
5 }
6 template <class U>
7 widget* Create(const U& arg, widget /* dummy */)
8 {
9 return new widget(arg, -1);
10 }
但是由于形参的传入,我们构造了一个临时对象,造成额外开销。我们需要一个轻量级的ID。就是Type2Type:
1 template <typename T>
2 struct Type2Type
3 {
4 typedef T OriginalType;
5 };
6
它没有任何数值,但它们各自不同型别。那么,现在可以这样写:
1 //依靠重载和Type2Type
2 template <class T, class U>
3 T* Create(const U& arg, Type2Type<T>)
4 {
5 return new T(arg);
6 }
7 template <class U>
8 widget* Create(const U& arg, Type2Type<widget>)
9 {
10 return new widget(arg, -1);
11 }
12 //cleint's code
13 String* pStr = Create("hello", Type2Type<string>());
14 widget* pW = Create(100, Type2Type<widget>());
第二个参数只是用来选择适合的重载函数。