上面例子中伸但,棧的實現(xiàn)使用了std::vector檬某。為了讓棧的實現(xiàn)更加靈活幌绍,我們將實現(xiàn)棧的容器也作為模板的參數(shù)之一又沾。
template<typename T, typename Container = std::vector<T>>
struct Stack
{
void push(const T& elem)
{
elems.push_back(elem);
}
T pop()
{
if(empty()) throw std::out_of_range("Stack<>::pop: empty!");
auto elem = elems.back();
elems.pop_back();
return elem;
}
bool empty() const
{
return elems.empty();
}
private:
Container elems;
};
如上我們?yōu)轭惸0逶黾恿艘粋€類型參數(shù)Container
倍权。和函數(shù)類似喇嘱,模板也支持聲明默認(rèn)參數(shù)否灾,這里我們將Container默認(rèn)設(shè)值為std::vector<T>
奸攻。由于在模板的形參聲明過程中匆背,后面的聲明可以使用前面出現(xiàn)過的形參呼伸,我們在typename Container = std::vector<T>
中使用了T,因此這里std::vector<T>
仍舊可看做是一個具體類型靠汁。
現(xiàn)在我們還可以像之前一樣使用該類模板蜂大,當(dāng)使用Stack<int>
定義intStack
時Container使用默認(rèn)的std::vector<T>
。同時我們可以顯示指定Container為別的容器類蝶怔,例如Stack<int, std::deque<int>> intStack;
奶浦。
每個用于替換形參Container的具體類型,必須滿足Stack使用Container時的隱式約束踢星。例如上例中Stack使用了Container的無參構(gòu)造函數(shù)澳叉,調(diào)用了Container的push_back
,back
沐悦,pop_back
成洗,empty
接口,并且對每個接口的參數(shù)和返回值都有一定預(yù)期藏否。上面使用的std::vector<T>
和std::deque<T>
都滿足如上約束瓶殃。一旦不滿足,會出現(xiàn)編譯錯誤副签。
目前C++中遥椿,模板這種對參數(shù)特征的約束只能通過參數(shù)被使用的情況隱式推斷出來基矮,后續(xù)的標(biāo)準(zhǔn)后可能會引進concept的特性使程序員可以對約束顯式化描述。