目录
- 什么是非类型模板参数?
- 非类型的类模板参数
- 非类型的函数模板参数
- 非类型模板参数的局限性
- 限制使用的场景
- 支持使用的场景
什么是非类型模板参数?
在函数模板和类模板中,模板参数并不仅仅可以当作类型,还可以当作普通值。当使用普通值作为模板参数时,调用者就必须显式的指定这些值。
非类型的类模板参数
例如 设置一个固定长度的列表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也不支持。 - 类对象不允许作为非类型模板参数
- 字符串常量不允许作为非类型模板参数
- 全局指针不允许作为非类型模板参数
支持使用的场景
- 常量整数
- 枚举值
- 对象指针