函數模闆
以下以取最大值的函數模闆maximum為例。此函數在編譯時會自動産生對應輸入變量的資料類型的實際代碼。
#include <iostream>
template <typename T>
inline const T& maximum(const T& x,const T& y)
{
if(y > x)
return y;
else
return x;
}
int main(void)
{
using namespace std;
//Calling template function
std::cout << maximum<int>(3,7) << std::endl; //輸出 7
std::cout << maximum(3, 7) << std::endl; //和上面相同
std::cout << maximum<double>(3.0,7.0) << std::endl; //輸出 7
return 0;
}
類别模闆
以下以将元件指針的操作,封裝成類别模闆ComPtr為例。
#pragma once
template <typename Ty>
class ComPtr
{
protected:
Ty* m_ptr;
public:
ComPtr()
{
m_ptr = NULL;
}
ComPtr(const ComPtr& rhs)
{
m_ptr = NULL;
SetComPtr(rhs.m_ptr);
}
ComPtr(Ty* p)
{
m_ptr = NULL;
SetComPtr(p);
}
~ComPtr()
{
Release();
}
const ComPtr& operator=(const ComPtr& rhs)
{
SetComPtr(rhs.m_ptr);
return *this;
}
Ty* operator=(Ty* p)
{
SetComPtr(p);
return p;
}
operator Ty* ()
{
return m_ptr;
}
Ty* operator->()
{
return m_ptr;
}
operator Ty** ()
{
Release();
return &m_ptr;
}
operator void** ()
{
Release();
return (void**)&m_ptr;
}
bool IsEmpty()
{
return (m_ptr == NULL);
}
void SetComPtr(Ty* p)
{
Release();
m_ptr = p;
if (m_ptr)
{
m_ptr->AddRef();
}
}
void Release()
{
if (m_ptr)
{
m_ptr->Release();
m_ptr = NULL;
}
}
};
- Borland模型(包含模闆編譯模式):編譯器生成每個編譯單元中遇到的所有的模闆執行個體,并存放在相應的目标檔案中;連結器合并相同的模闆執行個體,生成可執行檔案。為了在每次模闆執行個體化時模闆的定義都是可見的,模闆的聲明與定義放在同一個.h檔案中。這種方法的優點是連結器隻需要處理目标檔案;這種方法的缺點是由于模闆執行個體被重複編譯,編譯時間被加長了,而且不能使用系統的連結器,需重新設計連結器。
- Cfront/查詢模型(分離(Separation)模闆編譯模式):AT&T公司的C++編譯器Cfront為解決模闆執行個體化問題,增加了一個模闆倉庫,用以存放模闆執行個體的代碼并可被自動維護。當生成一個目标檔案時,編譯器把遇到的模闆定義與目前可生成的模闆執行個體存放到模闆倉庫中。連結時,連結器的包裝程式(wrapper)首先調用編譯器生成所有需要的且不在模闆倉庫中的模闆執行個體。這種方法的優點是編譯速度得到了優化,而且可以直接使用系統的連結器;這種方法的缺點是複雜度大大增加,更容易出錯。使用這種模型的源程式通常把模闆聲明與非内聯的模闆成員分别放在.h檔案與模闆定義檔案中,後者單獨編譯。
- 混合(疊代)模型:g++目前是基于Borland模型完成模闆執行個體化。g++未來将實作混合模型的模闆執行個體化,即編譯器把編譯單元中的模闆定義與遇到的目前可實作的模闆執行個體存放在相應的目标檔案中;連結器的包裝程式(wrapper)調用編譯器生成所需的目前還沒有執行個體化的模闆執行個體;連結器合并所有相同的模闆執行個體。使用這種模型的源程式通常把模闆聲明與非内聯的模闆成員分别放在.h檔案與模闆定義檔案中,後者單獨編譯。