1.什么叫做特化,就是模板泛化的反义词,对某些特殊化。当我们建立了一个模板,我们希望把这个模板
中的某些泛化的东西特殊化。
2.从例子来看:
template <class Key>
struct hash{ };
这个hash是泛化,当Key被绑定了,它不再是一个 可变的了,例如:、
template<>
struct hash<char>
{
size_t operator()(char x) const { return x; }
};
template<>
struct hash<int>
{
size_t operator(int x) const { return x; }
};
template<>
struct hash<long>
{
size_t operator() (long x) const { return x; }
};
当我们制定了任何一个Key都会跑到第一段里去,但是当我们指定了char或int或long,都会跑到第二段里的重载。
假如我们使用:
cout<<hash<long>()(1000);
编译器会去找,当然,泛化可以,但是如果有特化,那么就会跑到第二段特化的代码里面。特化可以任意版本,
你想怎么写就怎么写。
2.偏特化 partial specialization
可以分为个数上的偏特化与范围上的偏特化。
(1)个数上的偏特化:
template <typename T, typename Alloc=....>
class vector
{
....
};
可以看到这个类有两个模板参数,假如我想绑定其中一个。但是Alloc是一个默认值。
假设我们要绑定T为一个bool值,如果让一个字节去代替一个bool值那就会很浪费,所以如果我们单独去设计这个类
用bool的参数,那就能够节省许多。
template<typename Alloc=.....>
class vector<bool,Alloc>
{
......
};
这就是一种语法,将T绑定为bool值,但是顺序必须是从左到右。不能说我绑定1,3,5特化,2,4泛化,这是不对的
(2)范围上的偏特化
假设我设计接收一个T,如果我要把这个范围缩小到为一个T*,缩小为一个指针范围。
那么我们应该先这么做:
template <typename T>
class C
{
....
};
做出一个泛化版本的。然后再写一个特化版本的:
template <typename T>
class C<T*>
{
....
};
这样,告诉编译器,使用者如果用的是指针,就用第二段代码。至于它指向什么,都可以。指向T
当然,第一段的T与第二段的T完全不是同一个东西,所以第二段也能写成这样:
template <typename U>
class C<U*>
{
....
};
作为一个class的设计者,如果这么设计的话,在编译器下如果这样使用:
C<string> obj1;
C<string*> obj2;
编译器就会根据你要调用的哪个代码来进行调用。