1. 非类型的类模板参数
在类的模板参数列表中,不一定是都是类型,或者适配器,也可以是一个数。
我们可以通过非类型的类模板指定固定长度的栈,这样做的好处是避免动态的内存管理。下面的代码中,我们通过指定Maxsize
来创建array
从而进一步固化内存,限制栈的长度。
template<typename T, std::size_t Maxsize>
class Stack {
std::array<T, Maxsize> v;
std::size_t n;
public:
Stack();
void push(const T&);
void pop();
const T& top() const;
bool empty() const { return n == 0; }
std::size_t size() const { return n; }
};
//使用
Stack<int, 20> intStack; // 20个int的Stack
当我们在使用的时候,需要针对Maxsize
来做一些改善,比如在push时,就需要考虑上限问题,同时也要更新参数。
template<typename T, std::size_t Maxsize>
void Stack<T, Maxsize>::push(const T& x)
{
assert(n < Maxsize); // 确定Stack未满
v[n] = x;
++n;
}
2. 非类型的函数模板参数
你也可以在函数模板中直接定义参数,比如:
template<int val, typename T>
T addvalue(T x)
{
return x+Val;
}
可以用来作函数的谓语,和lambda表达式一样(虽然我觉得并没有lambda好用)
std::vector<int> v{ 0, 1, 2};
std::vector<int> v2(3);
std::transform(v.begin(), v.end(), v2.begin(), addValue<1, int>);
for (auto x : v2) std::cout << x; // 123
在C++17中允许将非类型模板参数定义为auto,以接收任何允许作为非类型模板参数的类型。
emplate<typename T, auto Maxsize>
class Stack {
std::array<T, Maxsize> v;
size_type n;
public:
using size_type = decltype(Maxsize);
Stack();
void push(const T&);
void pop();
const T& top() const;
bool empty() const { return n == 0; }
size_type size() const { return n; }
};
C++14中允许auto作为返回类型:
// 如果在类外定义size成员函数要写为
template <typename T, auto Maxsize>
typename Stack<T, Maxsize>::size_type Stack<T, Maxsize>::size() const
{
return n;
}
// C++14中可写为
template <typename T, auto Maxsize>
auto Stack<T, Maxsize>::size() const
{
return n;
}