Nontype Class Template Parameters(非类型类模板参数)

原创 2017年01月03日 18:33:34

一、需求引入

上一篇博客实作了一个「元素个数可变」的stack   class。与之对比,你也可以实作另一种stack,透过一个固定大小(fixed-size)的 array来容纳元素。这样做的好处是不必考虑诸如内存管理之类的问题。然而array大小的决定是一件比较困难的事:array愈小则stack愈容易满溢,array愈大则愈容易造成空间浪费 。 一个可行的解决办法是让使用者指定array大小 , 这个大小也就是stack  的最大元素个数。


二、代码示例

 为了完成以上想法,我们应该把大小值当作一个  template parameter: 

#include <stdexcept> 
 
template <typename T, int MAXSIZE> 
class Stack { 
private: 

//  元素 
T elems[MAXSIZE]; 

//  当前的元素个数 
int numElems; 


public: 

 //  构造函数 
Stack();

// push 元素
void push(T const&); 

// pop 元素 
void pop(); 

//  传回  stack 顶端元素  
T top() const; 

// stack 是否为空 
bool empty() const { 
return numElems == 0; 
}  

// stack 是否已满 
bool full() const { 
return numElems == MAXSIZE; 

}; 
 
//  构造函数 

//  一开始并无任何元素 
template <typename T, int MAXSIZE> 
Stack<T,MAXSIZE>::Stack () : numElems(0) { 
//  不做任何事 

 
template <typename T, int MAXSIZE> 
void Stack<T,MAXSIZE>::push (T const& elem) { 
if (numElems == MAXSIZE) { 
throw std::out_of_range("Stack<>::push(): stack is full."); 

//  追加 
elems[numElems] = elem; 

//  元素总数加  1 
++numElems; 

 
template <typename T, int MAXSIZE> 
void Stack<T,MAXSIZE>::pop () { 
if (numElems <= 0) { 
throw std::out_of_range("Stack<>::pop(): empty stack."); 

//  元素总数减  1 
--numElems; 

 
template <typename T, int MAXSIZE> 
T Stack<T,MAXSIZE>::top () const { 
if (numElems <= 0) { 
throw std::out_of_range("Stack<>::top(): empty stack."); 

//  传回最后一个元素 
return elems[numElems - 1]; 


三、使用

使用上述  class template 时,必须同时指定   (1)   元素类型和   (2) stack 元素的最大数量: 
 
#include <iostream> 
#include <string> 
#include <cstdlib> 
#include "stack4.hpp" 
 
int main() { 


try { 

//  最多容纳  20  个  int  元素 
Stack<int,20> int20Stack; 

//  最多容纳  40  个  int  元素 
Stack<int,40> int40Stack; 

//  最多容纳  40  个  string  元素 
Stack<std::string,40>   stringStack; 
 
//  操控「最多容纳  20  个  int  元素」的那个  stack 
int20Stack.push(7); 
std::cout << int20Stack.top() << std::endl; 
int20Stack.pop(); 
 
//  操控「最多容纳  40  个  string  元素」的那个  stack 
stringStack.push("hello");  32 
std::cout << stringStack.top() << std::endl; 
stringStack.pop(); 

stringStack.pop(); 


} catch (std::exception const& ex) { 
std::cerr << "Exception: " << ex.what() << std::endl; 
return EXIT_FAILURE; //  传回一个错误状态码 



 
注意,每一个被实例化(instantiated) 的  class template 都有各自的类型。 (注:常见的误会是:上述三个  stacks  隶属同一类型。这是错误观念。)因此  int20Stack  和  int40Stack  是两个不同类型,不能互相进行隐式或显式转换,两者不能换用(彼此取代),也不能互相赋值。


你可以指定  non-type template parameters 的默认值: 

template <typename T = int, int MAXSIZE = 100> 
class Stack { 
... 
}; 


然而从设计角度来看,这样做并不恰当。Template parameters 的默认值应该符合大多数情况下的  要求, 然而把  int  当做预设元素类型, 或指定  stack  最多有  100  个元素, 并不符合一个 「通用型 stack」 的需求。 更好的作法是让使用者指定这两个参数的值, 并在文件中说明它们的意义

版权声明:本文为博主原创文章,未经博主允许不得转载。

非类型模板参数与 非类型类模板参数的使用

函数模板和类模板,模板参数并不局限于类型,普通值也可以作为模板参数。 当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化,并获得最终代码...
  • makenothing
  • makenothing
  • 2015年11月13日 17:15
  • 934

模板非类型形参的详细阐述

关于模板的非类型形参,网上有很多内容,C++primer只有大概一页的阐述,但是都不够清晰详细。下面我尽可能从自己的角度去给大家描述一下非类型形参的相关细节。如果想进一步理解非类型形参以及模板内容可以...
  • u012999985
  • u012999985
  • 2016年03月02日 15:34
  • 2560

[运行时获取模板类类型] Java 反射机制 + 类型擦除机制

运行时获取模板类T的类型:Java 反射机制 + 类型擦除机制。
  • TBWood
  • TBWood
  • 2014年11月03日 17:59
  • 6902

C++ 模板类的默认模板参数、模板函数不支持默认模板参数

C++函数模板
  • u013321328
  • u013321328
  • 2014年06月15日 22:01
  • 1696

c++通用模板类(template class)定义实现详细介绍

有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类:class Compare_int { public : Compare(int a,int b) { x=a; y=...
  • u013443618
  • u013443618
  • 2015年11月20日 11:11
  • 5701

C++基础——非类型模板参数

非类型模板参看,顾名思义,模板参数不限定于类型,普通值也可作为模板参数。 1. 非类型类模板参数 2. 非类型函数模板参数 3. 非类型模板参数的限制 (1). 如何以非常量类型(double或...
  • lanchunhui
  • lanchunhui
  • 2015年11月04日 10:17
  • 3025

三、非类型模板参数(Nontype Template Parameters)

对于函数模板和类模板,模板参数不一定必须是类型,也可是是常规的数值。当以类型(type)作为模板参数的时候,代码中未决定的是类型;当以一般的数字(non-type)作为模板参数的时候,代码中待定的内容...
  • Mrhiuser
  • Mrhiuser
  • 2017年12月29日 16:24
  • 56

模板类 Template Classes 以及模板类编译时的处理

我们可以建立template classes,使它们能够神奇地操作任何类型的资料。下面这个例子是让CThree 类别储存三个成员变量,成员函数Min 传回其中的最小值,成员函数Max 则传回其中的最大...
  • PINBODEXIAOZHU
  • PINBODEXIAOZHU
  • 2015年08月17日 11:14
  • 800

怎样用boost::serialization去序列化派生模板类(续)

在 怎样用boost::serialization去序列化派生模板类这篇文章中,介绍了序列化派生类模板类, 在写测试用例时一直出现编译错误,调了很久也没跳出来,今天偶然试了一下...居然调了出来...
  • yanziguilai
  • yanziguilai
  • 2014年05月05日 00:26
  • 1826

C++之:模板元编程(三) 默认模板参数

一、类模板的默认模板参数原则  1、可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值。函数模板和类模板都可以为模板的非类型形参提供默认值。  2、类模板的类型形参默认值形式为:t...
  • Scythe666
  • Scythe666
  • 2016年03月24日 14:49
  • 2655
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Nontype Class Template Parameters(非类型类模板参数)
举报原因:
原因补充:

(最多只允许输入30个字)