C++非类型模板参数
对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数。在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定。但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化。
本文地址:http://www.cnblogs.com/archimedes/p/cpp-template-type.html,转载请注明源地址。
在上篇文章(C++类模板)中我们介绍了一个stack类模板作为例子,下面将看一个新版本的stack模板,来叙述本文将要介绍的特性:
非类型的类模板参数
创建类的头文件
#include<stdexcept>
#include<iostream>
using namespace std; template<typename T, int MAXSIZE>
class Stack{
private:
T elems[MAXSIZE];
int numElems;
public:
Stack();
void push(T const&);
void pop();
T top() const;
bool empty() const {
return numElems == ;
}
bool full() const {
return numElems == MAXSIZE;
}
}; template<typename T, int MAXSIZE>
Stack<T, MAXSIZE>::Stack():numElems() {} template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::push(T const& elem)
{
if(numElems == MAXSIZE) {
throw out_of_range("Stack<>::push(): stack is full");
}
elems[numElems] = elem;
++numElems;
} template<typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::pop()
{
if(numElems <= ) {
throw out_of_range("Stack<>::pop(): stack is full");
}
--numElems;
} template<typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::top() const
{
if(numElems <= ) {
throw out_of_range("Stack<>::top(): stack is full");
}
return elems[numElems - ];
}
stack4.h
实现代码:
#include<iostream>
#include<vector>
#include<deque>
#include<stdexcept>
#include<string>
#include<cstdlib>
#include "stack4.h"
using namespace std; int main()
{
try {
Stack<int, > int20Stack;
Stack<int, > int40Stack;
Stack<string, > stringStack; int20Stack.push();
cout<<int20Stack.top()<<endl;
int20Stack.pop(); stringStack.push("hello");
cout<<stringStack.top()<<endl;
stringStack.pop();
stringStack.pop();
}
catch(exception const& ex) {
cerr<<"Exception: "<<ex.what()<<endl;
//return EXIT_FAILURE;
} cin.get();
return ;
}
main
MAXSIZE是新加入的第二个模板参数,类型为int,它指定了数组最多可包含的栈元素的个数
同样,我们可以为模板参数指定缺省值:
template<typename T = int, int MAXSIZE = 100>
class Stack {
...
};
非类型的函数模板参数
你也可以为函数模板定义非类型参数。例如:
template<typename T, int VAL>
T addValue(T const& x)
{
return x + VAL:
}
借助于STL,可以传递这个函数模板的实例化给集中的每一个元素,让他们都增加一个整数值:
std::transform(source.begin(), source.end(), dest.begin(), (int(*)(int const&))addValue<int, >);
非类型模板参数的限制
非类型模板参数是有限制的,通常而言,它们可以是常整数(包括枚举值)或者指向外部链接对象的指针。
浮点数和类对象是不允许作为非类型模板参数的:
template<double VAT>
double process(double v) //error
{
return V * VAT;
} template<string name> //error
class MyClass {
...
};
另外,你也不能使用全局指针作为模板参数:
template<char const* name>
class MyClass{
...
}; char const* s = "hello";
MyClass<s> x; //s是一个指向内部连接对象的指针
但是你可以这样使用:
template<char const* name>
class MyClass {
...
}; extern char const s[] = "hello";
MyClass<s> x; //OK
全局字符数组s由"hello"初始化,是一个外部链接对象
C++非类型模板参数的更多相关文章
- C++ Template之非类型模板参数
非类型模板参数是通过基本变量类型引入,例如int,在使用时必须显式自定值,不能通过推断. 非类型模板参数的限制:不能是浮点数(在vc6.0上测试可以为浮点型),对象以及指向内部链接对象的指针. #in ...
- C++标准库函数 end 的实现原理(非类型模板参数)
在刚开始学习<C++ Primer>的时候遇到了 end 函数,感觉很神奇,但又很迷惑:为什么能获得数组的尾后指针呢?编译器也不会在内存中申请一块空间放数组元素的个数啊!最近再一次遇到了 ...
- c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters
类模板的非类型模板参数 函数模板的非类型模板参数 限制 使用auto推断非类型模板参数 模板参数不一定非得是类型,它们还可以是普通的数值.我们仍然使用前面文章的Stack的例子. 类模板的非类型模板参 ...
- 《深入实践C++模板编程》之三——模板参数类型详解
非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板. 1.整 ...
- 读书笔记 effective c++ Item 44 将与模板参数无关的代码抽离出来
1. 使用模板可能导致代码膨胀 使用模板是节省时间和避免代码重用的很好的方法.你不需要手动输入20个相同的类名,每个类有15个成员函数,相反,你只需要输入一个类模板,然后让编译器来为你实例化20个特定 ...
- C++模板参数类型(转载)
实际上有三种类型模板参数:类型模板参数.无类型模板参数和模板模板参数(以模板作为模板的参数). .类型模板参数 类型模板参数是我们使用模板的主要目的.我们可以定义多个类型模板参数: template& ...
- c++11-17 模板核心知识(十二)—— 模板的模板参数 Template Template Parameters
概念 举例 模板的模板参数的参数匹配 Template Template Argument Matching 解决办法一 解决办法二 概念 一个模板的参数是模板类型. 举例 在c++11-17 模板核 ...
- c++特性:指向类成员的指针和非类型类模板参数和函数指针返回值 参数推导机制和关联型别
一.c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针 格式如下: class A { public: void func(){printf("This is a funct ...
- C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则
背景: 最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言: ...
随机推荐
- repo: 创建local manifest以及如何添加app到CM/Android build系统中
The local manifest Creating a local manifest allows you to customize the list of repositories on you ...
- unity4.6 failed to update unity web player
unity4.6 failed to update unity web player 新升级的 4.6.2P2 版本修复了IOS很多的bug. 但突然发现导出的Web版本反而不能工作了. “faile ...
- ruby -- 问题解决(一)无法连接mysql数据库
>rails g controller home index 运行该命令时无法连接mysql 先下载配置文件:mysql-connector-c-noinstall-6.0.2-win32. ...
- NPTL 线程同步方式
NPTL提供了互斥体 pthread_mutex_t 类型进行线程同步,防止由于多线程并发对全局变量造成的不正确操作.使用 pthread_mutext_t 对数据进行保护已经可以实现基本的数据同步, ...
- struts2基础——最简单的一个例子
学习版本:struts-2.3.15.3 一.导入jar包,可以参考 官方项目 blank. 二.添加配置文件:web.xml struts.xml web.xml: <filter> & ...
- idea上实现github代码同步
1.先将github远程仓库clone到本地 2.将本地仓库中的项目导入到idea中 3.如果你的项目代码不是放在仓库的根目录下,idea会识别到你的项目是在git仓库目录下,必须点击add root ...
- 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message
Language: Default Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 21 ...
- 重构第12天 分解依赖(Break Dependencies)
理解:“分解依赖” 是指对部分不满足我们要求的类和方法进行依赖分解,通过装饰器来达到我们需要的功能. 详解:今天我们所讲的这个重构方法对于单元测试是非常有用的.如果你要在你的代码中加入单元测试但有一部 ...
- C#设计模式——状态模式(State Pattern)
一.概述在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为.如果用if else或是switch case等方法处理,对象操作及对象的状态就耦合在一起,碰到复杂的情况就会造成代码结构 ...
- 循序渐进开发WinForm项目(5)--Excel数据的导入导出操作
随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...