C++的非类型模板参数与模板分离编译(模板显式实例化)

非类型模板参数与模板分离编译(模板显式实例化)

文章目录

  • 非类型模板参数与模板分离编译(模板显式实例化)
    • 前言
    • 一、非类型模板参数
    • 二、模版分离编译
      • 1. 分离编译概念
      • 2. 模版的分离编译
        • 问题案例
        • 解决方法
    • 总结

前言

​ 本篇博客文章介绍了C++中的非类型模板参数和模板分离编译的概念。非类型模板参数是模板中的常量参数,可以在模板中当作常量使用,但不允许使用浮点数、类对象和字符串作为非类型模板参数。模板分离编译是将程序分为多个源文件进行单独编译生成目标文件,然后将目标文件链接为单一的可执行文件。文章还介绍了解决模板分离编译问题的方法,包括模板显式实例化和重新定义普通函数。最后,文章总结了模板的优点和缺点。


一、非类型模板参数

模板参数分类类型形参与非类型形参。

  • 类型形参即:出现在模板参数列表中,跟在 class 或者 typename 之类的参数类型名称。
template<typename T>
  • 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
template<size_t VAL = 100>

示例代码:

// 定义一个模板类型的静态数组
template<typename T, size_t N = 10>
class Array
{
public:T& operator[](size_t index) { return _array[index]; }const T& operator[](size_t index)const { return _array[index]; }size_t size()const { return _size; }bool empty()const { return 0 == _size; }
private:T _array[N];size_t _size = N;
};
void test1()
{Array<int> a;cout << a.size() << endl;		// 10cout << sizeof(a) << endl;		// 44	(x86下size_t占4字节)
}

注意:

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的
  2. 非类型的模板参数必须在编译期就能确认结果

二、模版分离编译

1. 分离编译概念

​ 一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

2. 模版的分离编译

问题案例

情景案例:假设现在主函数需要用到 add() 模板函数,但是 add() 函数保留了C风格的定义规范:“.h文件声明,.c文件定义”

代码如下:

// .h
template<typename T>
T add(T a, T b);// .c
#include "addFunc.h"template<typename T>
T add(T a, T b)
{return a + b;
}// main.c 调用外部文件的 add() 函数
#include "addFunc.h"
void test2()
{int a = 10;int b = 20;cout << add(a, b) << endl;
}

对代码进行编译:

在这里插入图片描述

可以看到编译是通过的,说明不存在语法错误。

接着运行代码:

在这里插入图片描述

出现链接报错,说明文件的最后合并工作未能成功。

利用g++编译器处理cpp代码的指令选项与后缀对应关系:

  1. 预处理(生成 .i 文件)
g++ -E source.cpp -o source.i
  1. 编译(生成 .s 文件)
g++ -S source.i -o source.s
  1. 汇编(生成 .o/.obj 文件)
g++ -c source.s -o source.o
  1. 链接(生成 可执行 文件)
g++ source.o -o executable

在这里插入图片描述

解决方法
  1. 模板定义的位置显式实例化。这种方法不实用,不推荐使用。

注意:.c文件中对模板函数的定义不需要变化,也不需要新建实例化函数的定义

// .h
template<typename T>
T add(T a, T b);// 方法1:模版显式实例化
template int add<int>(int, int);// .c
#include "addFunc.h"template<typename T>
T add(T a, T b)
{return a + b;
}
  1. 重新定义普通函数

注意:可以与模版函数同时存在,函数调用遵从优先匹配原则,但是.c文件要增加该新普通函数的定义

// .h
template<typename T>
T add(T a, T b);
// 方法2:重新定义普通函数
int add(int a, int b);// .c
#include "addFunc.h"template<typename T>
T add(T a, T b)
{return a + b;
}int add(int a, int b)	// 新增普通函数定义
{return a + b;
}
  1. 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。

注意:为了便于区分头文件内函数是否定义与声明分离,一般可以将.h文件改为.hpp文件标识

// .h
// 方法3:直接定义声明都放在.h文件(不搞声明和定义分离)
template<typename T>
T add(T a, T b)
{return a + b;
}
// .c 文件为空

总结

【优点】

  • 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  • 增强了代码的灵活性

【缺点】

  • 模板会导致代码膨胀问题,也会导致编译时间变长
  • 出现模板编译错误时,错误信息非常凌乱,不易定位错误

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/575463.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Appium设备交互API

设备交互API指的是操作设备系统中的一些固有功能&#xff0c;而非被测程序的功能&#xff0c;例如模拟来电&#xff0c;模拟发送短信&#xff0c;设置网络&#xff0c;切换横竖屏&#xff0c;APP操作&#xff0c;打开通知栏&#xff0c;录屏等。 模拟来电 make_gsm_call(phon…

OpenCV 如何使用 XML 和 YAML 文件的文件输入和输出

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;如何利用OpenCV4.9离散傅里叶变换 下一篇: 目标 本文内容主要介绍&#xff1a; 如何使用 YAML 或 XML 文件打印和读取文件和 OpenCV 的文本条目&#xff1f;如何对 OpenCV …

springcloud微服务项目,通过gateway+nacos实现灰度发布(系统不停机升级)

一、背景 灰度发布的目的是保证系统的高可用&#xff0c;不停机&#xff0c;提升用户体验。在微服务系统中&#xff0c;原有系统不下线&#xff0c;新版系统与原有系统同时在线&#xff0c;通过访问权重在线实时配置&#xff0c;可以让少量用户先应用新版本功能&#xff0c;如…

HCIA-Datacom H12-811 题库补充(3/28)

完整题库及答案解析&#xff0c;请直接扫描上方二维码&#xff0c;持续更新中 OSPFv3使用哪个区域号标识骨干区域&#xff1f; A&#xff1a;0 B&#xff1a;3 C&#xff1a;1 D&#xff1a;2 答案&#xff1a;A 解析&#xff1a;AREA 号0就是骨干区域。 STP下游设备通知上游…

3.Labview字符串与路径精讲(下) — 字符串及路径的使用

本章讲解labview中的字符串和路径具体实践用例&#xff0c;从前面板字符串属性到后面板字符串函数应用做出详细概述&#xff0c;通过本文的学习希望大家了解到字符串及路径在labview编程中的重要地位。 本系列文章为labview 从基础到强化到精通的学习文章&#xff0c;大家可以随…

uniApp使用XR-Frame创建3D场景(6)播放模型动画

上篇文章讲述了如何将XR-Frame作为子组件集成到uniApp中使用 这篇我们讲解播放模型动画 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"> <xr-node visible"{{sec6}}"><xr-light type"ambient&qu…

新手体验OceanBase社区版V4.2:离线部署单节点集群

本文源自OceanBase用户的分享 先简单总结如下&#xff1a; 1.本文适合初学者体验OceanBase社区版 v4.2.2 2.仅需准备一台配置为2C/8G的Linux虚拟机 3.通过离线方式安装&#xff0c;以便更直观地了解安装过程 一、Linux系统准备 在宿主机(即你的windows PC电脑)上安装vbox软…

CSS(二)---【常见属性、复合属性使用】

零.前言 本篇文章主要阐述CSS常见属性、复合属性&#xff0c;更多前置知识请见作者其它文章&#xff1a; CSS(一)---【CSS简介、导入方式、八种选择器、优先级】-CSDN博客 1.CSS属性 CSS的属性有上百个&#xff0c;但是我们并不需要全部学习&#xff0c;只要我们学习一部分…

LLM之RAG实战(三十五)| 使用LangChain的3种query扩展来优化RAG

RAG有时无法从矢量数据库中检索到正确的文档。比如我们问如下问题&#xff1a; 从1980年到1990年&#xff0c;国际象棋的规则是什么&#xff1f; RAG在矢量数据库中进行相似性搜索&#xff0c;来查询与国际象棋规则问题相关的相关文档。然而&#xff0c;在某些情况下&#xff0…

echarts 3D示例 echart, echarts-gl

echarts官网有很多的炫酷的3D模型 来尝试实现下&#xff0c;使用原本的柱状图或者折线图代码创建echarts示例,使用cdn的方式引入echarts <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewp…

新网站收录时间是多久,新建网站多久被百度收录

对于新建的网站而言&#xff0c;被搜索引擎收录是非常重要的一步&#xff0c;它标志着网站的正式上线和对外开放。然而&#xff0c;新网站被搜索引擎收录需要一定的时间&#xff0c;而且时间长短受多种因素影响。本文将探讨新网站收录需要多长时间&#xff0c;以及新建网站多久…

边缘计算AI盒子目前支持的AI智能算法、视频智能分析算法有哪些,应用于大型厂矿安全生产风险管控

一、前端设备实现AI算法 主要是基于安卓的布控球实现&#xff0c;已有的算法包括&#xff1a; 1&#xff09;人脸&#xff1b;2&#xff09;车牌&#xff1b;3&#xff09;是否佩戴安全帽&#xff1b;4&#xff09;是否穿着工装&#xff1b; 可以支持定制开发 烟雾&#xf…