Posted on 2006-02-05 04:40
Tommy Liang 阅读(1394)
评论(1) 编辑 收藏 引用 所属分类:
泛型编程与设计模式
就是这样一个结构:
template <typename T>
struct Type2Type
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
typedef T OriginalType;
};假定有个片断如下,创建一个T*
template <class T,class U>
T* Create(const U& arg)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return new T(arg);
}如果对于某个类如“Widget”,其ctor要有两个参数,比如第二个参数必须是-1(对于旧的代码来说,谁知道呢:)),但又不想另外创建一个“CreateWidget”方法,那么怎么办呢,函数是不能偏特化的,即如下代码:
在 VC7下会报告:非法使用显式模板参数
只能使用函数重载,比如:
template <class T,class U>
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
T* Create(const U&arg,T /**//*虚拟*/)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return new T(arg);
}
![](/Images/OutliningIndicators/None.gif)
template <class U>
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Widget * Create(const U& arg, Widget /**//*虚拟*/)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return new Widget(arg,-1);
}
这样是可以解决问题,但最大的毛病在于运行时构造了 未被使用的对象这个开销(虚拟的Widget参数)。这时 Type2Type 这个咚咚出场了,按照书的说法,这是“一个型别代表物、一个可以让你传给重载函数的轻量级ID”,如下:
template <class T,class U>
T* Create(const U& arg,Type2Type<T>)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return new T(arg);
}
![](/Images/OutliningIndicators/None.gif)
template <class U>
Widget * Create(const U& arg,Type2Type<Widget>)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
return new Widget(arg,-1);
}
![](/Images/OutliningIndicators/None.gif)
调用方:
String *pStr = Create("hello",Type2Type<String>());
Widget *pW = Create(100,Type2Type<Widget>());
关键是,这个东西也是给编译器看的,妙