对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数。在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定。但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化。

本文地址: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++非类型模板参数的更多相关文章

  1. C++ Template之非类型模板参数

    非类型模板参数是通过基本变量类型引入,例如int,在使用时必须显式自定值,不能通过推断. 非类型模板参数的限制:不能是浮点数(在vc6.0上测试可以为浮点型),对象以及指向内部链接对象的指针. #in ...

  2. C++标准库函数 end 的实现原理(非类型模板参数)

    在刚开始学习<C++ Primer>的时候遇到了 end 函数,感觉很神奇,但又很迷惑:为什么能获得数组的尾后指针呢?编译器也不会在内存中申请一块空间放数组元素的个数啊!最近再一次遇到了 ...

  3. c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters

    类模板的非类型模板参数 函数模板的非类型模板参数 限制 使用auto推断非类型模板参数 模板参数不一定非得是类型,它们还可以是普通的数值.我们仍然使用前面文章的Stack的例子. 类模板的非类型模板参 ...

  4. 《深入实践C++模板编程》之三——模板参数类型详解

    非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板.   1.整 ...

  5. 读书笔记 effective c++ Item 44 将与模板参数无关的代码抽离出来

    1. 使用模板可能导致代码膨胀 使用模板是节省时间和避免代码重用的很好的方法.你不需要手动输入20个相同的类名,每个类有15个成员函数,相反,你只需要输入一个类模板,然后让编译器来为你实例化20个特定 ...

  6. C++模板参数类型(转载)

    实际上有三种类型模板参数:类型模板参数.无类型模板参数和模板模板参数(以模板作为模板的参数). .类型模板参数 类型模板参数是我们使用模板的主要目的.我们可以定义多个类型模板参数: template& ...

  7. c++11-17 模板核心知识(十二)—— 模板的模板参数 Template Template Parameters

    概念 举例 模板的模板参数的参数匹配 Template Template Argument Matching 解决办法一 解决办法二 概念 一个模板的参数是模板类型. 举例 在c++11-17 模板核 ...

  8. c++特性:指向类成员的指针和非类型类模板参数和函数指针返回值 参数推导机制和关联型别

    一.c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针 格式如下: class A { public: void func(){printf("This is a funct ...

  9. C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则

    背景:    最近在学习C++STL,出于偶然,在C++Reference上看到了vector下的emplace_back函数,不想由此引发了一系列的“探索”,于是就有了现在这篇博文. 前言:     ...

随机推荐

  1. repo: 创建local manifest以及如何添加app到CM/Android build系统中

    The local manifest Creating a local manifest allows you to customize the list of repositories on you ...

  2. unity4.6 failed to update unity web player

    unity4.6 failed to update unity web player 新升级的 4.6.2P2 版本修复了IOS很多的bug. 但突然发现导出的Web版本反而不能工作了. “faile ...

  3. ruby -- 问题解决(一)无法连接mysql数据库

     >rails g controller home index  运行该命令时无法连接mysql 先下载配置文件:mysql-connector-c-noinstall-6.0.2-win32. ...

  4. NPTL 线程同步方式

    NPTL提供了互斥体 pthread_mutex_t 类型进行线程同步,防止由于多线程并发对全局变量造成的不正确操作.使用 pthread_mutext_t 对数据进行保护已经可以实现基本的数据同步, ...

  5. struts2基础——最简单的一个例子

    学习版本:struts-2.3.15.3 一.导入jar包,可以参考 官方项目 blank. 二.添加配置文件:web.xml struts.xml web.xml: <filter> & ...

  6. idea上实现github代码同步

    1.先将github远程仓库clone到本地 2.将本地仓库中的项目导入到idea中 3.如果你的项目代码不是放在仓库的根目录下,idea会识别到你的项目是在git仓库目录下,必须点击add root ...

  7. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

  8. 重构第12天 分解依赖(Break Dependencies)

    理解:“分解依赖” 是指对部分不满足我们要求的类和方法进行依赖分解,通过装饰器来达到我们需要的功能. 详解:今天我们所讲的这个重构方法对于单元测试是非常有用的.如果你要在你的代码中加入单元测试但有一部 ...

  9. C#设计模式——状态模式(State Pattern)

    一.概述在面向对象软件设计时,常常碰到某一个对象由于状态的不同而有不同的行为.如果用if else或是switch case等方法处理,对象操作及对象的状态就耦合在一起,碰到复杂的情况就会造成代码结构 ...

  10. 循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...