2.6 Partial Specialization
2.6 偏特化
Class templates can be partially specialized. You can provide special implementations for particular circumstances, but some template parameters must still be defined by the user. For example, we can define a special implementation of class Stack<> for pointers:
类模板可以被偏特化。你可以在特定的场景下指定类模板的特定实现,但某些模板参数仍然必须由用定来定义。例如可以为类Stack<>特化实现一个指针版本:
#include "stack1.hpp" //为类Stack<>局部特化,实现一个指针版本 template<typename T> class Stack<T*> { private: std::vector<T*> elems; // elements public: void push(T*); // push element T* pop(); // pop element T* top() const; // return top element bool empty() const { // return whether the stack is empty return elems.empty(); } }; template<typename T> void Stack<T*>::push (T* elem) { elems.push_back(elem); // append copy of passed elem } template<typename T> T* Stack<T*>::pop () { assert(!elems.empty()); T* p = elems.back(); elems.pop_back(); //删除最后一个元素 return p; // 然后返回它(不像一般的情况) } template<typename T> T* Stack<T*>::top () const { assert(!elems.empty()); return elems.back(); // return copy of last element }
With
template<typename T> class Stack<T*> { };
we define a class template, still parameterized for T but specialized for a pointer(Stack<T*>).
通过template<typename T> class<T*>{},我们定义了一个模板参数为T的类模板,但使用的是指针类型来特化(Stack<T*>)。
Note again that the specialization might provide a (slightly) different interface. Here, for example, pop() returns the stored pointer, so that a user of the class template can call delete for the removed value, when it was created with new:
再次注意,特化可能提供(略微)不同的接口。例如,这里的pop()函数返回存储的指针。这样,类模板使用者可以在用new创建新值时,调用delete来删除旧值。
Stack< int*> ptrStack; // stack of pointers (特化实现) ptrStack.push(new int{42}); std::cout << *ptrStack.top() << ’ ’; delete ptrStack.pop();
Partial Specialization with Multiple Parameters
多参数的偏特化
Class templates might also specialize the relationship between multiple template parameters. For example, for the following class template:
类模板还可以特化多个模板参数之间的关系。例如,下面的类模板:
template<typename T1, typename T2> class MyClass { … };
the following partial specializations are possible:
可以进行以下的偏特化:
// 局部特化:两个模板参数的类型相同 template<typename T> class MyClass<T,T> { … }; // 局部特化:第2个参数为int template<typename T> class MyClass<T,int> { … }; // 局部特化:两个模板参数都是指针类型 template<typename T1, typename T2> class MyClass<T1*,T2*> { … };
The following examples show which template is used by which declaration:
下面的例子演示了哪个声明使用了哪个模板:
MyClass< int, float> mif; //使用 MyClass<T1,T2> MyClass< float, float> mff; //使用 MyClass<T,T> MyClass< float, int> mfi; // 使用 MyClass<T,int> MyClass< int*, float*> mp; // 使用 MyClass<T1*,T2*>
If more than one partial specialization matches equally well, the declaration is ambiguous:
如果有多个局部特化同等程度地匹配某个声明,那么就称该声明具有二义性。
MyClass< int, int> m; // 错误:匹配MyClass<T,T>和MyClass<T,int> MyClass< int*, int*> m; //错误:匹配MyClass<T,T> 和 MyClass<T1*,T2*>
To resolve the second ambiguity, you could provide an additional partial specialization for pointers of the same type:
为了解决第2种二义性,你可以另外提供一个指向相央类型指针的特化:
template<typename T> class MyClass<T*,T*> { … };
For details of partial specialization, see Section 16.4 on page 347.
至于更多的细节,请参阅347页的16.4节。