一、非類型模板參數(shù)
簡(jiǎn)單點(diǎn)說(shuō)就是在定義模板時(shí)脖祈,模板的類型參數(shù)不是一個(gè)泛型的 T,而是一個(gè)具體的類型刷晋。這種比較多的是在比如定就義容器類模板時(shí)盖高,指定容器的容量大小。如下 SStack 的定義眼虱。
template<typename T, std::size_t MaxSize>
class SStack{
private:
std::array<T, MaxSize> elems;
std::size_t numElems;
public:
SStack();
void push(const T& t);
void pop();
const T& top() const;
bool empty() const {
return numElems == 0;
}
std::size_t size() const {
return numElems;
}
};
template<typename T, std::size_t MaxSize>
SStack<T, MaxSize>::SStack() {}
template<typename T, std::size_t MaxSize>
void SStack<T, MaxSize>::push(const T &t) {
assert(numElems < MaxSize);
elems[numElems] = t;
++numElems;
}
template<typename T, std::size_t MaxSize>
void SStack<T, MaxSize>::pop() {
assert(!elems.empty());
--numElems;
}
template<typename T, std::size_t MaxSize>
const T& SStack<T, MaxSize>::top() const{
assert(!elems.empty());
return elems[numElems-1];
}
下面是使用代碼
SStack<float, 30> sStack30;
SStack<float, 50> sStack50;
看起來(lái)還是很簡(jiǎn)單的喻奥,誰(shuí)說(shuō)不是呢?
二捏悬、非類型模板參數(shù)的限制
非類型模板參數(shù)并不是所有類型都可以的撞蚕,是有一定限制的:
-
只能是整型常量包括枚舉,比如过牙,如果是個(gè) std::string 則會(huì)報(bào)以下錯(cuò)誤信息甥厦。
image.png 指向 objects/function/members 的指針或者引用。但注意抒和,指針?biāo)赶虻膶?duì)象不能是字符串常量矫渔、局部變量或者數(shù)據(jù)成員及其子類對(duì)象彤蔽。而且摧莽,這里還有版本的差異。在 C++11 中顿痪,要求指針?biāo)傅膶?duì)象必須是 extern 的镊辕,而在 C++ 14 則要求必須 extern 或者文件內(nèi)的全局變量,而在 C++ 17 后蚁袭,這些限制都放寬了征懈。
objects/function 的左值引用,或者 nullptr揩悄。
三卖哎、使用 auto 關(guān)鍵字使非類型模板參數(shù)的類型更加泛化
使用 auto 關(guān)鍵字作為非類型模板參數(shù)時(shí)的定義
template<typename T, auto MaxSize>
class AutoStack{
private:
std::array<T, MaxSize> elems;
using size_type = decltype(MaxSize);
size_type numElems;
public:
AutoStack();
void push(const T& t);
void pop();
const T& top() const;
bool empty() const {
return numElems == 0;
}
auto size() const {
return numElems;
}
};
template<typename T, auto MaxSize>
AutoStack<T, MaxSize>::AutoStack() {}
template<typename T, auto MaxSize>
void AutoStack<T, MaxSize>::push(const T &t) {
assert(numElems < MaxSize);
elems[numElems] = t;
++numElems;
}
template<typename T, auto MaxSize>
void AutoStack<T, MaxSize>::pop() {
assert(!elems.empty());
--numElems;
}
template<typename T, auto MaxSize>
const T& AutoStack<T, MaxSize>::top() const{
assert(!elems.empty());
return elems[numElems-1];
}
上面有兩個(gè)比較有意思的地方,一個(gè)是可以通過(guò) decltype 返回 auto 的實(shí)際類型從而來(lái)定義 numElems 屬性。另一個(gè)是 size() 方法的返回屬性可以用 auto 關(guān)鍵字來(lái)讓編譯器自動(dòng)推導(dǎo)亏娜。真的是妙啊焕窝。
四肴掷、總結(jié)
- 通過(guò)非類型模板參數(shù)伴郁,我們可以知道模板的參數(shù)類型不一定非得是類型,也可以是數(shù)值帆啃。只不過(guò)這個(gè)數(shù)值是有一定限制的溯泣,具體限制看第 2 點(diǎn)虐秋。
- 不可以將浮點(diǎn)型或者 class 類型的對(duì)象用于非類型模板參數(shù)。使用指向字符串常量垃沦,臨時(shí)變量和子對(duì)象的指針或者引用也有一些限制客给。
- 使用 auto 關(guān)鍵字,可以使非類型模板參數(shù)的類型更加泛化肢簿。