非类型模板参数(参考《C++ Templates 英文版第二版》)
非类型模板参数(参考《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 英文版第二版》)相关推荐
- 类模板(参考《C++ Templates 英文版第二版》)
类模板(参考<C++ Templates 英文版第二版>) Chapter 1 类模板 与函数相似,类也可以被一个或者多个类型参数化 在这章,我们使用栈作为例子 2.1 类模板stack的 ...
- 函数模板(参考《C++ Templates 英文版第二版》)
C++模板编程(参考<C++ Templates 英文版第二版>) Chapter 1 函数模板 1.1 一窥函数模板 template<class T> T max(T a, ...
- C++知识点60——非类型模板参数
模板参数不仅可以使类型,也可以是值.可以用特定的类型名(比如int)而非typename或者class表示非类型模板参数.当模板被实例化时,非类型模板参数会被一个值而不是类型替代.非类型模板参数 一. ...
- C++非类型模板参数
对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这 ...
- java两个函数名字相同_为什么C不允许两个具有相同名称的函数/类模板,只有非类型模板参数(整数类型)的类型不同?...
我尝试这个时编译器会出错 . 我试过VC和g . 这同样适用于函数模板和类模板(但对于函数模板,只有在实例化函数模板时才会出现编译器错误;当编译器遇到第二个类定义时,会立即出现类模板的编译器错误) . ...
- C++17 非类型模板参数的auto 和 DevC++ 支持C++17
模板参数分为两种,一种是类型模板参数,也是我们用得最多的一种: template <typename T, typename U> auto add(T t, U u) { ret ...
- C++ 泛型编程(二):非类型模板参数,模板特化,模板的分离编译
目录 非类型模板参数 函数模板的特化 类模板的特化 全特化 偏特化 部分参数特化 参数修饰特化 模板分离编译 问题分析 解决方法 非类型模板参数 模板的参数分为两种,一种是非类型参数,一种是类型参数. ...
- C++基础——非类型模板参数
非类型类模板参数 非类型函数模板参数 非类型模板参数的限制 非类型模板参看,顾名思义,模板参数不限定于类型,普通值也可作为模板参数.在基于类型的模板中,模板实例化时所依赖的是某一类型的模板参数,你定义 ...
- C++模板(函数模板,类模板)的基本使用与非类型模板参数与模板的特化
C++模板 模板初阶 泛型编程 函数模板 函数模板概念 函数模板格式 函数模板的原理 函数模板的实例化 隐式实例化 显式实例化:在函数名后的<>中指定模板参数的实际类型 模板参数的匹配原则 ...
最新文章
- python定义的关键数据类型_Python基本数据类型
- 2019年pta作业第二题——求最大值及其下标
- golang中的json
- HPC China2016全国高性能计算学术年会即将举行
- NSUserDefaults的用法(轻量级本地数据存储)
- Hibernate陷阱
- linux java amr转mp3_本工具用于将微信语音 amr 格式转换为 mp3 格式以便在 html5 的 audio 标签中进行播放...
- 显示器分辨率一直跳_2020如何选择适合自己的显示器?小白选购电脑显示器必看!...
- 潭州Java中级班(day_13)-异常概述
- 页面编码和js文件不同导致的IE6下脚本错误
- 十分钟了解websql和indexedDB
- Python爬虫--爬取电影天堂网站电影下载地址
- java 枚举类使用反射
- 基于thinkphp开源cms 对比
- 计算机硬盘根目录是什么,根目录是什么(d盘根目录是什么意思)
- 谈谈web打印快递单及经验
- 信息学奥赛IO三大法宝
- 5G笔记| 概述:5G三大应用场景、5G关键技术概览
- 51CTO与我的大学生活
- 微信小程序使用MQTT远程控制单片机——阿里云物联网平台