类模板的特化,偏特化

来源:互联网 发布:数据库管理第三版答案 编辑:程序博客网 时间:2024/04/27 20:01

本文来自C++ Templates:


Class Templates 的特化(Specializations)


你可以针对某些特殊的模板参数,对一个类模板进行特化。类模板的特化与函数模板的重載类似,使你得以针对某些特定类型进行代码优化,或修正某個特定类型在函数模板具现化中的错误行为。

然而如果你对一个类模板进行特化,就必須特化其所有成元函式。虽然你可以特化某個单独的成员函式,但一旦这么做,也就不再是特化整個 class template。


欲特化某個 class template,必須以 template<> 开头申明此类,后面跟着你希望的特化結果。特化类型將作为模板参数 并在 class 称之后直接写明:

template<>
class Stack<std::string> {
 ...
};

对特化体而言,每個成員函式都必須像常規的成員函式那樣定义,每一個 T 出現處都必須更換為特化类型:

void Stack<std::string>::push (std::string const& elem)
{
 elems.push_back(elem); // 將傳入的 elem 附加於尾
}

下面是一個针对 std::string 类型而特化的 Stack<> 的完整範例:


#include <deque>
#include <string>
#include <stdexcept>
#include "stack1.hpp"

template<>
class Stack<std::string> {
private:
std::deque<std::string> elems;     // 元素
public:
void push(std::string const&);     // push 元素
void pop();                        // pop 元素

std::string top() const;           // 傳回 stack 最頂端元素

bool empty() const {               // stack 是否為空

return elems.empty();

 }

};


void Stack<std::string>::push (std::string const& elem)
{
  elems.push_back(elem); // 追加元素

}


void Stack<std::string>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<std::string>::pop(): empty stack");
  }
elems.pop_back(); // 移除最後㆒個元素

}


std::string Stack<std::string>::top () const
{
 if (elems.empty()) {
throw std::out_of_range("Stack<std::string>::top(): empty stack");
}

return elems.back(); // 傳回最後㆒個元素的拷貝

}


偏特化

Class templates可以被偏特化(或稱部份特化、局部特化)。這使你得以在特定情形下使用特殊实现码,但仍然留給你選擇 template parameters 的能力。


例如對於下面的 class template:


template <typename T1, typename T2>
class MyClass {
...
};

以下數種形式的偏特化都是合理的:

// 偏特化:兩個 template parameter 相同
template <typename T>
class MyClass<T,T> {
 ...
};

// 偏特化:第二個类型為 int
template <typename T>
class MyClass<T,int> {
 ...
};

// 偏特化:兩個 template parameter 均為指標类型
template <typename T1, typename T2>
class MyClass<T1*, T2*> {
 ...
};

以下例子示範,下列各式使用上述哪一個 class template:

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*>

如果某個宣告式與兩個(或更多)偏特化版本產生同等的匹配程度,這個宣告式便被視為模稜兩可(歧義):

MyClass<int,int> m; // 錯誤:同時匹配 MyClass<T,T> 和 MyClass<T,int>

MyClass<int*,int*> m; // 錯誤:同時匹配 MyClass<T,T> 和 MyClass<T1*,T2*>

為解除上述第二宣告的歧義性,你可以針對「指向相同类型」的指针,提供另㆒個偏特化版本:

template <typename T>
class MyClass<T*,T*> {
 ...
};

0 0