Linux
Linux software install
Google repo的使用
Vector AP StartApplication编译脚本解析
Yocto的cmake版本升级
不能自动安装的解决方式
S32G-BSP35.0-SDK使用方法
S32G从SDK生成文件系统的制作过程
Linux Samba设置
Linux添加双网卡
S32G USB-Redirector安装指南
VS code自动生成Doxygen格式注释
Linux下使用多线程下载
使用pandoc 生成带中文的pdf
minicom无法输入的问题解决办法
使用 systemd unit 添加一条路由规则
CMake 教程
步骤 1:基本起点
步骤 2:添加lib库
步骤 3:为库添加使用要求
步骤 4:添加生成器表达式
步骤 5:安装和测试
步骤 6:添加支持测试仪表板
步骤 7: 添加系统内省
步骤 8:自定义命令和生成的文
步骤 9:打包安装程序
步骤 10:选择静态库或共享库
步骤 11:添加导出配置
步骤 12:打包 Debug 和 Release
添加虚拟网卡
Vector AP 去掉防篡改校验
Vector AP startapplication编译与使用
Vector AP问题汇总
Vector AP大型项目开发流程
Vector AP EM
Vector AP 最简单的开发示例
Linux kernel 版本降级
Vector AP StartApplicaiton
startappplication-machine-design
startapplicaiton-machine-integration
amsr-vector-fs-em-executionmanager-design
amsr-vector-fs-em-executionmanager
Vector AP 复杂模型的开发
第一章 Machine和MachineDesign
第二章 Execute Manager
第三章 Log
第四章 State Manager
第五章 State Manager 源码的理解
第六章 Someip daemon
第七章 IPC Service Discovery Daemon
crond的使用方法
解决蓝牙鼠标在 Ubuntu 中单位时间内断开的问题
VPS服务器自建教程
v2rayA的客户端使用配置
GDB调试指南入门篇:揭开程序运行世界的神秘面纱
GDB调试指南高级篇:成为调试专家,掌控程序的命运
Linux安装PyQt5并配置Qt Designer
ADB 命令大全
GoogleTest(一)
GoogleTest(二)简单的TEST宏
GoogleTest(三)简单类函数测试
C++ Template
1. 函数模板
2. 类模板
3. 非类型模板参数
软件版本号规范
EPOLL
C++手札
C++ 使用{}初始化有哪些好处?
现代 C++ decltype 深入解析
函数对象(functor)
Linux性能剖析:CPU、内存、网络与I/O压力测试
AP StateManager
C++ Lambda表达式
C++ 中的Lambda表达式
Lambda 表达式语法
Lambda 表达式的示例
手动发送UDP数据包
pyqt5生成的UI界面不能输入中文
自己搭建repo镜像
摄影
Sony仿富士PP值设置
诗词歌赋
本文档使用 MrDoc 发布
-
+
首页
3. 非类型模板参数
## 前言 模板参数未必都是typename的关键字,也可以是**某种类型的`变量`** # 类模板的非类型参数 ## 声明 ```cpp template<typename T, std::size_t Maxsize> class Stack; ``` ## 定义 ```cpp template<typename T, std::size_t Maxsize> //要理解这句 class Stack { ... }; ``` `typename T`这类型 `std::size_t Maxsize`这是变量 ## 引用 ```cpp template<typename T, std::size_t Maxsize> class Stack { private: std::array<T, Maxsize> elems; // elements std::size_t numElems; // current number of elements public: Stack(); // constructor void push(T const& elem); // push element void pop(); // pop element T const& top() const; // return top element bool empty() const { //return whether the stack is empty return numElems == 0; } std::size_t size() const { //return current number of elements return numElems; } }; template<typename T, std::size_t Maxsize> Stack<T, Maxsize>::Stack() : numElems(0) { // nothing to do in constructor } 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 } int main() { Stack<int,20> int20Stack; // stack of up to 20 ints Stack<int,40> int40Stack; // stack of up to 40 ints Stack<std::string,40> stringStack; // stack of up to 40 strings // manipulate stack of up to 20 ints int20Stack.push(7); std::cout << int20Stack.top() << std::endl; int20Stack.pop(); // manipulate stack of up to 40 strings stringStack.push("hello"); std::cout << stringStack.top() << std::endl; stringStack.pop(); return 0; } ``` 也可是指定非模板参数的默认值。虽然说对于本例来说,并没有多大意义,但是只是为了说明赋默认值是可行的。eg: ```cpp template<typename T, std::size_t Maxsize = 100> \\Maxsize默认值是100 class Stack { … }; ``` # 函数模板的非类型参数 ## 声明 ```cpp template<int Val, typename T> T addValue (T x); ``` ## 定义 ```cpp template<int Val, typename T> T addValue (T x) { return x + Val; } ``` ## 引用 例如当使用 C++标准库给一个集合中的所有元素增加某个值的时候, 可以将这个函数模板的一个实例化版本用作第 4个参数: ```cpp std::transform (source.begin(), source.end(), //start and end of source dest.begin(), //start of destination addValue<5,int>); // operation ``` 第 4 个参数是从 addValue<>()实例化出一个可以给传入的 int 型参数加 5 的函数实例。 这一 实例会被用来处理集合 source 中的所有元素, 并将结果保存到目标集合 dest 中。 >注意在这里必须将 addValue<>()的模板参数 T 指定为 int 类型。 因为类型推断只会对立即发 生的调用起作用, 而 std::transform()又需要一个完整的类型来推断其第四个参数的类型。 目 前还不支持先部分地替换或者推断模板参数的类型, 然后再基于具体情况去推断其余的模板 参数。 **同样也可以基于前面的模板参数推断出当前模板参数的类型。 比如可以通过传入的非类型模 板参数推断出返回类型** ```cpp template<auto Val, typename T = decltype(Val)> T foo(); ``` 或者可以通过如下方式确保传入的非类型模板参数的类型和类型参数的类型一致: ```cpp template<typename T, T Val = T{}> T bar(); ``` # 非类型模板参数的限制 ## 类型限制 使用非类型模板参数是有限制的。 通常它们只能是整形常量( 包含枚举),指向对象/函数/成员的指针。对象或者函数对象的左值引用。或者是 std::nullptr_t(类型是 nullptr) ## 避免无效表达式 非类型模板参数可以是任何编译器表达式。比如: ```cpp template<int I, bool B> class C; … C<sizeof(int) + 4, sizeof(int)==4> c; ``` 不过如果在表达式中使用了 operator >, 就必须将相应表达式放在括号里面, 否则>会被作为 模板参数列表末尾的>, 从而截断了参数列表: ```cpp C<42, sizeof(int) > 4> c; // ERROR: first > ends the template argument list C<42, (sizeof(int) > 4)> c; // OK ``` # 使用 auto 作为非模板类型参数的类型 从 C++17 开始, 可以不指定非类型模板参数的具体类型( 代之以 auto) , 从而使其可以用 于任意有效的非类型模板参数的类型。 通过这一特性, 可以定义如下更为泛化的大小固定的 Stack 类: ```cpp #include <array> #include <cassert> template<typename T, auto Maxsize> class Stack { public: using size_type = decltype(Maxsize); private: std::array<T,Maxsize> elems; // elements size_type numElems; // current number of elements public: Stack(); // constructor void push(T const& elem); // push element void pop(); // pop element T const& top() const; // return top element bool empty() const { //return whether the stack isempty return numElems == 0; } size_type size() const { //return current number of elements return 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 } ``` 通过使用 auto 的如下定义: ```cpp template<typename T, auto Maxsize> class Stack { … }; ``` 定义了类型待定的 Maxsize。 它的类型可以是任意非类型参数所允许的类型。 在模板内部, 既可以使用它的值: ```cpp std::array<T,Maxsize> elems; // elements ``` 也可以使用它的类型: ```cpp using size_type = decltype(Maxsize); ``` 然后可以将它用于成员函数 size()的返回类型: ```cpp size_type size() const { //return current number of elements return numElems; } ``` 从 C++14 开始, 也可以通过使用 auto, 让编译器推断出具体的返回类型: ```cpp auto size() const { //return current number of elements return numElems; } ```
admin
2024年9月3日 14:48
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码