对于函数模板和类模板,模板参数并不局限于类型,普通值也可以作为模板参数。

文章目录

  • 非类型的类模板参数
  • 非类型的函数模板参数
  • 非类型模板参数的限制
  • 总结

非类型的类模板参数

#include <stdexcept>template <typename T, int MAXSIZE>
class Stack{private:int elems[MAXSIZE];     //包含元素数组int numElems;           //元素的当前个数
public:Stack();                //构造函数void push(T const&);    //压入元素void pop();             //弹出元素T top() const;          //返回栈顶元素bool empty() const {    //返回栈是否为空rerurn numElems == 0;}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){trow std::out_of_range("Stack<>::push(): Stack is full!");}elems[numElems] = elem;  //附加元素++numElems;   //增加元素的个数
}//弹出元素
template <typename T, int MAXSIZE>
void Stack<T, MAXSIZE>::pop()
{if (numElems <= 0){trow std::out_of_range("Stack<>::push(): empty Stack!");}--numElems;  //减少元素的个数
}//返回栈顶元素
template <typename T, int MAXSIZE>
T Stack<T, MAXSIZE>::top() const
{if (numElems <= 0){trow std::out_of_range("Stack<>::push(): empty Stack!");}return elems[numElems-1];  //返回最后一个元素
}

为了使用上述模板,必须同时指定元素的类型和个数(即栈的最大元素容量)。

Stack<int, 20> int20Stack;
Stack<int, 40> int40Stack;
Stack<std::string, 40> stringStack;

当然,上面的模板同样可以为模板参数设置缺省值

template <typename T = int, int MAXSIZE = 99>
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, 5>;   //操作(或者函数)

上面的调用,最后一个实参实例化的函数模板addValue(),它上int元素加5。源集合source中的每一个元素都会加5将结果存在目标集合中。下面是一个使用std::transform()函数的例子:

#include "Stack.hpp"
#include <iostream>
#include <vector>
#include <algorithm>template<typename T, int VAL>
T addValue(T const& x)
{return x + VAL;
}int main()
{std::vector<int> source;source.push_back(1);source.push_back(2);source.push_back(3);std::vector<int> dest;dest.resize(source.size()); //这一句不能少!!!std::transform(source.begin(), source.end(),            dest.begin(),                           (int(*)(int const&))addValue<int, 5>);for (int i = 0; i < dest.size(); i++){std::cout << dest[i] << " ";}system("pause");return 0;
}

非类型模板参数的限制

非类型模板参数是有限制的,通常是常整数(包括枚举值)或者指向外部链接对象的指针。
浮点数类对象是不允许作为非类型模板参数:

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"初始化,是一个外部链接对象。

总结

模板参数不但可以是类型,也可以是值。
非类型模板参数,不能使用浮点数、class类的对象和内部链接对象(例如string)作为实参。
详情参考:《C++Templates》

C++ 非类型的模板参数相关推荐

  1. c++模板 --- 类模板、自定义类型当做模板参数

    生成一个类模板 类中用到了未知类型叫做类模板 用 template 修饰的类,这个类就是一个模板类 多用在数据结构中,忽略类型的问题 只要被 template 修饰,就是一个模板类,有没有用未知类型都 ...

  2. C++ 泛型编程(二):非类型模板参数,模板特化,模板的分离编译

    目录 非类型模板参数 函数模板的特化 类模板的特化 全特化 偏特化 部分参数特化 参数修饰特化 模板分离编译 问题分析 解决方法 非类型模板参数 模板的参数分为两种,一种是非类型参数,一种是类型参数. ...

  3. 非类型模板参数(参考《C++ Templates 英文版第二版》)

    非类型模板参数(参考<C++ Templates 英文版第二版>) Chapter 3 3.1 非类型类模板参数 与前几章的简单例子不同,你也可以通过std::array实例化一个固定大小 ...

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

    非类型类模板参数 非类型函数模板参数 非类型模板参数的限制 非类型模板参看,顾名思义,模板参数不限定于类型,普通值也可作为模板参数.在基于类型的模板中,模板实例化时所依赖的是某一类型的模板参数,你定义 ...

  5. 模板的模板参数与非类型模板参数

    模板参数-实现容器适配器 我们在学习栈和队列时,通过数组或链表实现,这里C++提供一种实现方式:容器适配器. 用vector或者list为容器,适配出一个stack或queue,具体是如何实现? 基本 ...

  6. 浅谈非类型模板参数、模板的特化

    非类型模板参数 1.模板参数分类类型形参与非类型形参. 2.类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称.类型参数也可以给缺省值 3.非类型形参,就是用一个常 ...

  7. C++知识点60——非类型模板参数

    模板参数不仅可以使类型,也可以是值.可以用特定的类型名(比如int)而非typename或者class表示非类型模板参数.当模板被实例化时,非类型模板参数会被一个值而不是类型替代.非类型模板参数 一. ...

  8. binarytreenode”使用 类 模板 需要 模板 参数列表_c++1117 模板核心知识(一)—— 函数模板...

    目录 定义函数模板 使用函数模板 两阶段翻译 Two-Phase Translation 模板的编译和链接问题 多模板参数 引入额外模板参数作为返回值类型 让编译器自己找出返回值类型 将返回值声明为两 ...

  9. C++非类型模板参数

    对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这 ...

  10. java两个函数名字相同_为什么C不允许两个具有相同名称的函数/类模板,只有非类型模板参数(整数类型)的类型不同?...

    我尝试这个时编译器会出错 . 我试过VC和g . 这同样适用于函数模板和类模板(但对于函数模板,只有在实例化函数模板时才会出现编译器错误;当编译器遇到第二个类定义时,会立即出现类模板的编译器错误) . ...

最新文章

  1. javascript publish/subscribe or observer pattern
  2. 【技术贴】虚拟机 VMware win7 win8网卡驱动下载 解决虚拟机不识别网卡没有本地连接...
  3. 面试题编程题06-python 输入一个字符串,反转输出
  4. P3374 【模板】树状数组 1
  5. 解决无法安装cnpm,cnpm卡顿问题
  6. 响应式 媒体查询 盒模型
  7. 设计模式-Builder和Factory模式区别
  8. Mysql 无法插入中文,中文乱码解决
  9. 30天自制操作系统 pdf_30天自制操作系统:第三天:系统引导完成
  10. 配置hadoop 使用fair scheduler调度器
  11. php+windows+信号,php 处理信号简单演示
  12. 安装spinningup填坑ERROR: Could not build wheels for mpi4py which use PEP 517
  13. B. Shifting Sort- Codeforces Round #744 (Div. 3)
  14. HTML5期末大作业:个人网页设计——薛之谦6页(代码质量好) 学生DW网页设计作业源码 web课程设计网页规划与设计
  15. 2022最新性能测试面试题(带答案)
  16. JAVA基础学习(二)
  17. 如何删除PDF中指定的一页或几页?
  18. 笔记本电脑安装 OMV 关闭屏幕自动休眠的问题
  19. IMPLEMENTATION MANUAL SWAN Cycle III version 41.31
  20. (附源码)springboot 个人健康管理 毕业设计 202031

热门文章

  1. docker+阿里云镜像容器进行环境的备份与获取
  2. 一步一步搭建ZooKeeper + Mesos + Marathon平台管理Docker集群
  3. IOS开发之Target-Action模式
  4. 真希望能夠統一一下接口
  5. PHP - ReflectorClass 反射类的作用
  6. Magento首页不显示产品
  7. 6.数据结构 --- 树和二叉树
  8. 11.GitLab webhooks
  9. 48. 减少 DNS 查找(9)
  10. 49. Element removeAttribute() 方法