什么是非类型模板参数?
在函数模板和类模板中,模板参数并不仅仅可以当作类型,还可以当作普通值。当使用普通值作为模板参数时,调用者就必须显式的指定这些值。
非类型的类模板参数
例如 设置一个固定长度的列表MyList
。且模板参数有 数据类型和容量大小。
只有在增加新的元素时才会与容器大小进行比较。第二个模板参数就是非类型的类模板参数。
具体代码如下:
template<class T, uint32_t SIZE> class MyList { MyList(); void PushBack(); void PopFront(); private: list m_data; uint32_t m_size; }; template<class T, uint32_t SIZE> MyList<T, SIZE>::MyList() :m_size{0} { } template<class T, uint32_t SIZE> void MyList<T, SIZE>::PushBack() { if (m_size >= SIZE) { throw out_of_range("MyList<>::PushBack() list is full! "); } // ... 功能代码 } template<class T, uint32_t SIZE> void MyList<T, SIZE>::PopFront() { // ... 功能代码 }
非类型的函数模板参数
同样函数模板也支持非类型的模板参数。例如配合C++的算法库algorithm
中的std::transform
方法进行全部元素增加。
#include <iostream> #include <algorithm> #include <vector> using namespace std; template<typename T, int VAL> T addValue(T const& x) { return x + VAL; } int main() { vector<int> vec{ 9,5,1,2,3,4 }; transform(vec.begin(), vec.end(), vec.begin(), addValue<int, 5>); for (const auto& elem : vec) { cout << elem << " "; } cout << endl; return 0; }
函数模板当作回调函数使用时,就需要显式的指定函数模板参数类型。
非类型模板参数的局限性
非类型模板参数也是有要求的,不是所有的类型都支持。
限制使用的场景
- 浮点数不允许作为非类型模板参数
虽然提示使用C++20标准,但20也不支持。 - 类对象不允许作为非类型模板参数
- 字符串常量不允许作为非类型模板参数
- 全局指针不允许作为非类型模板参数
支持使用的场景
- 常量整数
- 枚举值
- 对象指针