模板参数不仅可以使类型,也可以是值。可以用特定的类型名(比如int)而非typename或者class表示非类型模板参数。当模板被实例化时,非类型模板参数会被一个值而不是类型替代。非类型模板参数
一、类模板的非类型模板参数
仍然拿mystack举例,需要加一个int类型的模板参数,表示栈中能容纳元素的最大数目
template <typename T, int maxcount, typename CONT = deque<T>>
class mystack
{
public:
mystack();
mystack(const mystack<T, maxcount, CONT> &rval);
mystack<T, maxcount, CONT> &operator=(const mystack<T, maxcount, CONT> &rval);
~mystack();
void push(const T &ele);
void pop();
T top() const;
bool empty() const {
return elem.empty();
}
private:
CONT elem;
};
template <typename T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::mystack()
{
cout<<__func__<<endl;
}
template <class T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::mystack(const mystack<T, maxcount, CONT> &rval):elem(rval.elem)
{
cout<<__func__<<endl;
}
template <class T, int maxcount, typename CONT>
mystack<T, maxcount, CONT> & mystack<T, maxcount, CONT>::operator=(const mystack<T, maxcount, CONT> &rval)
{
cout<<__func__<<endl;
if (this==&rval) {
return *this;
}
this->elem=rval.elem;
return *this;
}
template <typename T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::~mystack()
{
cout<<__func__<<endl;
}
template <typename T, int maxcount, typename CONT>
void mystack<T, maxcount, CONT>::push(const T &ele)
{
if (elem.size()>=maxcount) {
return;
}
cout<<__func__<<endl;
elem.push_back(ele);
}
template <typename T, int maxcount, typename CONT>
void mystack<T, maxcount, CONT>::pop()
{
cout<<__func__<<endl;
try {
elem.pop_back();
}
catch (out_of_range){
cout<<"out_of_range"<<endl;
}
}
template <typename T, int maxcount, typename CONT>
T mystack<T, maxcount, CONT>::top() const
{
cout<<__func__<<endl;
try {
return elem.back();
}
catch (out_of_range){
cout<<"out_of_range"<<endl;
}
}
因为新加了一个模板参数,所以成员函数的实现也要加一个模板参数,此外在push时,要判断栈中元素的个数是否超过了maxcount
int main(int argc, char const *argv[])
{
mystack<int, 20> si20;
si20.push(7);
cout<<si20.top()<<endl;
si20.push(8);
cout<<si20.top()<<endl;
si20.pop();
cout<<si20.top()<<endl;
return 0;
}
如果不想显式指明maxcount,可以将maxcount设置为默认模板实参
二、函数模板的非类型模板参数
函数模板也可以设置非类型模板参数
示例1
template <typename T, int val>
T addval(T &ele)
{
return ele+=val;
}
int main(int argc, char const *argv[])
{
list<int> l(10, 2);
for_each(l.begin(),l.end(), addval<int, 10>);
for (auto c:l) {
cout<<c<<",";
}
cout<<endl;
return 0;
}
示例2
template <unsigned m, unsigned n>
int compare(const char (&ra1)[m], const char (&ra2)[n])
{
cout<<m<<","<<n<<endl;
return strcmp(ra1, ra2);
}
int main(int argc, char const *argv[])
{
compare("1234", "qwe");
return 0;
}
编译器根据字符串的sizeof推断出m和n的值为5和4
三、非类型模板参数的限制
1.浮点数和类类型不可以作为非类型模板参数
template <typename T, vector<int> s>
class test1
{
};
template <typename T, double d>
class test2
{
};
2.不能使用字符串常量和指针作为非类型模板参数的实参,但是数组可以
template <typename T, const char *ps>
class test1
{
};
const char *s="hi";
const char s1[]="hi";
int main(int argc, char const *argv[])
{
test1<int, s1> t1;
//test1<int, s> t2;
//test1<int, "hi"> t3;
return 0;
}
第12,13行需要注释掉
否则报错
参考
《C++ Template》
《C++ Primer》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出