使用C++有多年了,一直认为对C++还掌握得可以,但是昨天在webkit移植代码中看到下面一行代码:
template <> void freeOwnedGPtr<GdkEvent>(GdkEvent*);
半天也没有明白这种写法的含义。C++模板用得很少,但对于其写法还是知道一点的,但之前没有见过这种写法的。赶紧找来The C++ Programming Language,才了解到有一种专门化模板。
一般而言,一个模板给出了一个单一的定义,它可以用于用户可以想到的任何模板参数。对于某些写模板的人而言,这个规定不一定总有意义,可能想“如果模板参数是指针,就用这个实现;如果不是,就用那个实现”。许多这样的设计考虑都可以通过提供多个不同定义的方式来处理,并由编译器基于使用处所提供的模板参数,在这些定义中做出选择,即是专门化模板。
比如一个Vector模板:
template<class T> class Vector {
T* v;
int size;
public:
Vector();
explicit Vector(int);
T& elem(int i) { return v[i];}
T& operator[](int i);
void swap(Vector&);
// …
};
Vector<int> vi;
Vector<Shape*> vps;
Vector<char*> vpc;
Vector<Node*> vpn;
大部分Vector将是某种指针类型的Vector。这样做的原因很多,但最基本的原因是,为了保持多态性的行为方式就必须使用指针。
大部分C++实现的默认方式是对模板函数建立代码段的副本。对于运行效率而言,这种做法很好。但可能会导致严重的代码膨胀,就像上面Vector的例子。
通过专门化,可以使所有的指针容器都能共享同一份实现代码。首先,定义一个到void的指针的专门化Vector版本:
template<> class Vector<void*> {
void** p;
// …
void*& operator[](int i);
};
之后这个专门化就会被用作所有指针的Vector的共同实现了。
前缀template<>说明这是一个专门化,可以不用模板参数描述。这个专门化使用时的模板参数在名字之后的<>号里描述。<void*>说明这个定义应该用在所有的T是void*的Vector实现里。