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

Chapter 3

3.1 非类型类模板参数

与前几章的简单例子不同,你也可以通过std::array实例化一个固定大小的栈,这样做的优点在于内存管理,

#include <array>
#include <cassert>template<typename T, std::size_t Maxsize>
class Stack {private:std::array<T,Maxsize> elems; // elementsstd::size_t numElems;        // current number of elementspublic:Stack();                   // constructorvoid push(T const& elem);  // push elementvoid pop();                // pop elementT const& top() const;      // return top elementbool empty() const {       // return whether the stack is emptyreturn numElems == 0;}std::size_t size() const { // return current number of elementsreturn numElems;}
};template<typename T, std::size_t Maxsize>
Stack<T,Maxsize>::Stack (): numElems(0)                 // start with no elements
{// nothing else to do
}template<typename T, std::size_t Maxsize>
void Stack<T,Maxsize>::push (T const& elem)
{assert(numElems < Maxsize);elems[numElems] = elem;    // append element++numElems;                // increment number of elements
}template<typename T, std::size_t Maxsize>
void Stack<T,Maxsize>::pop ()
{assert(!elems.empty());--numElems;                // decrement number of elements
}template<typename T, std::size_t Maxsize>
T const& Stack<T,Maxsize>::top () const
{assert(!elems.empty());return elems[numElems-1];  // return last element
}

运行一下:

#include "stacknontype.hpp"
#include <iostream>
#include <string>int main()
{Stack<int, 20>         int20Stack;     // stack of up to 20 intsStack<int, 40>         int40Stack;     // stack of up to 40 intsStack<std::string, 40> stringStack;    // stack of up to 40 strings// manipulate stack of up to 20 intsint20Stack.push(7);std::cout << int20Stack.top() << '\n';int20Stack.pop();// manipulate stack of up to 40 stringsstringStack.push("hello");std::cout << stringStack.top() << '\n';stringStack.pop();
}

你也可以设置默认参数

template<typename T, std::size_t Maxsize = 100>,但最好不要这样做,因为栈大小最好还是有程序员自己控制

3.2 非类型函数模板参数

你也可以为函数定义非类型模板参数

template<int val,typename  T>
int addval(T a)
{return a + val;
}
int main()
{std::cout << addval<10>(10) << std::endl;
}

这种函数是很有用的,可以将它作为参数.

例如,如果你可以使用STL,你可以传入一个函数模板的实例,使集合中的每个数加一个值

 std::vector<int> source{ 1,4,5 };std::vector<int> dest{0,0,0};std::transform(source.begin(), source.end(), dest.begin(), addval<10,int>);for (auto value : dest){std::cout << value << std::endl;}

如果你制定非类型函数模板参数是int那么就无法使用其他类型,是有什么方法可以做到自动推导其他类型呢?

其实,你可以指定一个根据之前的模板参数推断出来的模板参数

template<auto val,typename  T = decltype(val)>
T addval(T a)
{return a + val;
}

3.3 非类型模板参数的限制

非类型模板参数有一些限制,例如,它们只能是整数,(对象,函数,成员)指针,(对象,函数,成员)引用,std::nullptr

浮点数指针和类对象不可以作为非类型模板参数

3.4 模板参数类型auto

C++17 ,你可以定义一个非类型模板模板参数去普遍的接收任何类型,使用这个特性,你可以定义一个更加一般的固定大小栈

#include <array>
#include <cassert>template<typename T, auto Maxsize>
class Stack {public:using size_type = decltype(Maxsize);private:std::array<T,Maxsize> elems; // elementssize_type numElems;          // current number of elementspublic:Stack();                   // constructorvoid push(T const& elem);  // push elementvoid pop();                // pop element T const& top() const;      // return top elementbool empty() const {       // return whether the stack is emptyreturn numElems == 0;}size_type size() const {   // return current number of elementsreturn numElems;}
};// constructor
template<typename T, auto Maxsize>
Stack<T,Maxsize>::Stack (): numElems(0)                 // start with no elements
{// nothing else to do
}template<typename T, auto Maxsize>
void Stack<T,Maxsize>::push (T const& elem)
{assert(numElems < Maxsize);elems[numElems] = elem;    // append element++numElems;                // increment number of elements
}template<typename T, auto Maxsize>
void Stack<T,Maxsize>::pop ()
{assert(!elems.empty());--numElems;                // decrement number of elements
}template<typename T, auto Maxsize>
T const& Stack<T,Maxsize>::top () const
{assert(!elems.empty());return elems[numElems-1];  // return last element
}

运行:

Stack<int, 20u>        int20Stack;     // stack of up to 20 intsStack<std::string, 40> stringStack;    // stack of up to 40 strings// manipulate stack of up to 20 intsint20Stack.push(7);std::cout << int20Stack.top() << '\n';auto size1 = int20Stack.size();// manipulate stack of up to 40 stringsstringStack.push("hello");std::cout << stringStack.top() << '\n';auto size2 = stringStack.size();if (!std::is_same_v<decltype(size1), decltype(size2)>) {std::cout << "size types differ" << '\n';}

非类型模板参数(参考《C++ Templates 英文版第二版》)相关推荐

  1. 类模板(参考《C++ Templates 英文版第二版》)

    类模板(参考<C++ Templates 英文版第二版>) Chapter 1 类模板 与函数相似,类也可以被一个或者多个类型参数化 在这章,我们使用栈作为例子 2.1 类模板stack的 ...

  2. 函数模板(参考《C++ Templates 英文版第二版》)

    C++模板编程(参考<C++ Templates 英文版第二版>) Chapter 1 函数模板 1.1 一窥函数模板 template<class T> T max(T a, ...

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

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

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

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

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

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

  6. C++17 非类型模板参数的auto 和 DevC++ 支持C++17

    模板参数分为两种,一种是类型模板参数,也是我们用得最多的一种: template <typename T, typename U> auto add(T t, U u) {     ret ...

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

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

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

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

  9. C++模板(函数模板,类模板)的基本使用与非类型模板参数与模板的特化

    C++模板 模板初阶 泛型编程 函数模板 函数模板概念 函数模板格式 函数模板的原理 函数模板的实例化 隐式实例化 显式实例化:在函数名后的<>中指定模板参数的实际类型 模板参数的匹配原则 ...

最新文章

  1. python定义的关键数据类型_Python基本数据类型
  2. 2019年pta作业第二题——求最大值及其下标
  3. golang中的json
  4. HPC China2016全国高性能计算学术年会即将举行
  5. NSUserDefaults的用法(轻量级本地数据存储)
  6. Hibernate陷阱
  7. linux java amr转mp3_本工具用于将微信语音 amr 格式转换为 mp3 格式以便在 html5 的 audio 标签中进行播放...
  8. 显示器分辨率一直跳_2020如何选择适合自己的显示器?小白选购电脑显示器必看!...
  9. 潭州Java中级班(day_13)-异常概述
  10. 页面编码和js文件不同导致的IE6下脚本错误
  11. 十分钟了解websql和indexedDB
  12. Python爬虫--爬取电影天堂网站电影下载地址
  13. java 枚举类使用反射
  14. 基于thinkphp开源cms 对比
  15. 计算机硬盘根目录是什么,根目录是什么(d盘根目录是什么意思)
  16. 谈谈web打印快递单及经验
  17. 信息学奥赛IO三大法宝
  18. 5G笔记| 概述:5G三大应用场景、5G关键技术概览
  19. 51CTO与我的大学生活
  20. 微信小程序使用MQTT远程控制单片机——阿里云物联网平台

热门文章

  1. 如何制作印章_如何用Photoshop制作个性印章/文字图片
  2. python和flask中返回JSON数据
  3. 前端状态机系列:SCXML与XState对应关系
  4. Awesome Tools Site
  5. Exynos4412 Uboot 移植(一)—— Uboot 编译流程分析
  6. 【Linux】FTP文件下载
  7. 对二维数组进行Zig-Zag扫描(C++)
  8. Linux 如何加载并口/打印口驱动
  9. react学习(69)--置空操作
  10. 前端学习(2970):首页的简单尝试