当前位置: 首页 > news >正文

C++模板基础(四)

函数模板(四)
● 函数模板的实例化控制
– 显式实例化定义: template void fun(int) / template void fun(int)

//header.h
template<typename T>
void fun(T x)
{std::cout << x << std::endl;
}
//main.cpp
#include"header.h"
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int x =3;fun<int>(x); //此处用int实例化函数模板,然后调用return a.exec();
}

在这里插入图片描述

//header.h
template<typename T>
void fun(T x)
{std::cout << x << std::endl;
}
template
void fun<int>(int x); //OK,显式实例化的定义,不需要写出函数模板的实现,编译的时候编译器自动生成实现template
void fun(int x); //OK,也是一个显式实例化的定义
//main.cpp
#include"header.h"
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int x =3;fun<int>(x); //头文件中已经有了一个显式实例化的版本,此处的调用刚好模板实参是int,所以此处直接调用函数模板的实例化版本return a.exec();
}

在这里插入图片描述

– 显式实例化声明: extern template void fun(int) / extern template void fun(int)

//header.h
//头文件中定义模板原型
template<typename T>
void fun(T x)
{std::cout << x << std::endl;
}
//source.cpp
//source.cpp中定义一个实例化
#include "header.h"
template
void fun<int>(int x);
//main.cpp
#include"header.h"//main.cpp中对函数模板的一个实例化的声明,在main.cpp这个翻译单元中不会再产生一个int型的实例: 减轻了编译器的负担也减轻了链接器的负担,一定程度上提升了编译和廉洁的速度
extern template //Since C++11, 模板实例化的一个声明
void fun<int>(int x);int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int x =3;fun<int>(x);return a.exec();
}

在这里插入图片描述

– 注意一处定义原则

//header.h
//头文件中定义模板原型
template<typename T>
void fun(T x)
{std::cout << x << std::endl;
}
//source.cpp
#include "header.h"
//source.cpp中定义一个实例化,满足模板翻译单元级别的一处定义原则
template
void fun<int>(int x);void g()
{fun<int>(100);
}
//main.cpp
#include"header.h"
//main.cpp中定义一个实例化,满足模板翻译单元级别的一处定义原则
template
void fun<int>(int x);int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int x =3;fun<int>(x);return a.exec();
}

以上代码在有的编译器上会编译并运行,但是在Qt5.14.2上报错:找到一个或多个重定义的符号
解释:An implementation is not required to diagnose a violation of this rule. 参考https://stackoverflow.com/questions/52664184/why-does-explicit-template-instantiation-not-break-odr

– 注意实例化过程中的模板形参推导

template<typename T>
void fun(T x)
{std::cout << x << std::endl;
}template<typename T>
void fun(T* x)
{std::cout << x << std::endl;
}template
void fun<int*>(int* x); //此处是template<typename T>void fun(T x)的实例化定义int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);return a.exec();
}
#include<iostream>
template<typename T>
void fun(T x)
{std::cout << "template<typename T> void fun(T x)" << x << std::endl;
}template<typename T>
void fun(T* x)
{std::cout << "template<typename T> void fun(T* x)" << x << std::endl;
}template //注意模板实例化的位置,在两个模板之后
void fun(int* x); //此处是template<typename T>void fun(T* x)的一个实例化int mian()
{
}
//https://cppinsights.io/里的编译输出结果
#include<iostream>
template<typename T>
void fun(T x)
{(std::operator<<(std::cout, "template<typename T> void fun(T x)") << x) << std::endl;
}template<typename T>
void fun(T * x)
{(std::operator<<(std::cout, "template<typename T> void fun(T* x)") << x) << std::endl;
}/* First instantiated from: insights.cpp:15 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun<int>(int * x)
{std::operator<<(std::cout, "template<typename T> void fun(T* x)").operator<<(reinterpret_cast<const void *>(x)).operator<<(std::endl);
}
#endiftemplate
void fun(int* x);int mian()
{
}
#include<iostream>
template<typename T>
void fun(T x)
{std::cout << "template<typename T> void fun(T x)" << x << std::endl;
}template //注意模板实例化的位置,在第一个模板之后,是template<typename T>void fun(T x)的实例化
void fun(int* x);template<typename T>
void fun(T* x)
{std::cout << "template<typename T> void fun(T* x)" << x << std::endl;
}int mian()
{
}
#include<iostream>
template<typename T>
void fun(T x)
{(std::operator<<(std::cout, "template<typename T> void fun(T x)") << x) << std::endl;
}/* First instantiated from: insights.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun<int *>(int * x)
{std::operator<<(std::cout, "template<typename T> void fun(T x)").operator<<(reinterpret_cast<const void *>(x)).operator<<(std::endl);
}
#endiftemplate
void fun(int* x);template<typename T>
void fun(T * x)
{(std::operator<<(std::cout, "template<typename T> void fun(T* x)") << x) << std::endl;
}int mian()
{
}

● 函数模板的 ( 完全 ) 特化: template<> void f(int) / template<> void f(int)
– 并不引入新的(同名)名称,只是为某个模板针对特定模板实参提供优化算法
– 注意与重载的区别
– 注意特化过程中的模板形参推导

参考
深蓝学院:C++基础与深度解析
C++ Insights

相关文章:

C++模板基础(四)

函数模板&#xff08;四&#xff09; ● 函数模板的实例化控制 – 显式实例化定义&#xff1a; template void fun(int) / template void fun(int) //header.h template<typename T> void fun(T x) {std::cout << x << std::endl; }//main.cpp #include&quo…...

pycharm使用记录

文章目录下载安装后续其他设置编辑器设置关于debug下载安装 直接去pycharm官网下载社区版&#xff0c;这个版本本来就是免费的&#xff0c;而且功能其实已经够了 后续其他设置 首先&#xff0c;第一次启动时&#xff0c;记得在preference->interpreter中设置python环境&a…...

Linux命令·kill·killall

Linux中的kill命令用来终止指定的进程&#xff08;terminate a process&#xff09;的运行&#xff0c;是Linux下进程管理的常用命令。通常&#xff0c;终止一个前台进程可以使用CtrlC键&#xff0c;但是&#xff0c;对于一个后台进程就须用kill命令来终止&#xff0c;我们就需…...

Linux /proc/version 文件解析

/proc/version文件里面的内容: Linux version 4.14.180-perf (oe-user@oe-host) (clang version 10.0.5 for Android NDK, GNU ld (GNU Binutils) 2.29.1.20180115) #1 SMP PREEMPT Wed Mar 29 18:55:02 CST 2023 /proc/version文件里面记录了如下内容: 1、Linux kernel的…...

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)

目录1. model编写数据表2. 管理员列表2.1 admin.py视图文件2.2 admin_list.html2.3 url.py2.4 最终效果3. 管理员添加3.0 md5包的书写3.1 form.py表单组件3.2 admin.py视图文件3.3 引入公共的添加数据html3.4 url.py3.5 最终效果4. 管理员编辑4.0 form表单组件4.1 admin.py视图…...

STL容器之<array>

文章目录测试环境array介绍头文件模块类定义对象构造初始化元素访问容器大小迭代器其他函数测试环境 系统&#xff1a;ubuntu 22.04.2 LTS 64位 gcc版本&#xff1a;11.3.0 编辑器&#xff1a;vsCode 1.76.2 array介绍 array是固定大小的序列式容器&#xff0c;它包含按严格…...

flask教程6:cookie和session

文章目录一、cookie1.1 什么是cookie&#xff1f;1.2 使用cookie1.2.1 设置cookie1.2.2设置cookie的有效期1.2.3在Flask中查询cookie1.2.4删除cookie二、session2.1实现session的两种思路2.1.1 第一种2.1.2 第二种2.2使用session2.2 .1设置session2.2.2 设置有效期2.2.3 获取se…...

【JavaEE初阶】第六节.网络原理TCP/IP协议

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、TCP/IP协议五层协议栈&#xff1b; 1.1 应用层协议&#xff1b; 二、传输层协议&#xff1b; 2.1 UDP协议&#xff1b; 2.2 TCP协议&#xff1b; 2.…...

模式识别 —— 第六章 支持向量机(SVM)与核(Kernel)

模式识别 —— 第六章 支持向量机&#xff08;SVM&#xff09;与核&#xff08;Kernel&#xff09; 文章目录模式识别 —— 第六章 支持向量机&#xff08;SVM&#xff09;与核&#xff08;Kernel&#xff09;硬间隔&#xff08;Hard-Margin&#xff09;软间隔&#xff08;Soft…...

总结 synchronized

目录synchronized的特性1. 互斥2. 刷新内存3. 可重入synchronized的使用1. 直接修饰普通方法2. 修饰静态方法3. 修饰代码块synchronized的锁机制基本特点关键锁策略 : 锁升级synchronized的特性 1. 互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized…...

360周鸿祎又“开炮”:GPT 6-8就将产生自主意识!我们来测算一下对错

‍数据智能产业创新服务媒体——聚焦数智 改变商业近日&#xff0c;360的周鸿祎放言“GPT6到GPT8人工智能将会产生意识&#xff0c;变成新的物种。未来&#xff0c;人工智能大语言模型有可能实现自我进化&#xff0c;自动更新系统和自我升级&#xff0c;或者指数级进化能力&am…...

python——飞机大战小游戏

目录 1、导入模块 2、窗口操作 3、事件操作 4、长按事件 5、添加游戏背景 6、添加英雄飞机 7、获取飞机的图片矩形 8、基本游戏窗口 9、添加游戏窗口图片 10、英雄飞机登场 11、英雄飞机装备子弹并发射 1、enemy_plane 2、game_main 3、game_map 4、game_score …...

数组(完全二叉树)向下建堆法与堆排序O(N*logN)

TIPS AdjustUp & AdjustDown向上调整AdjustUp与向下调整AdjustDown的参数是一个数组&#xff08;完全二叉树&#xff09;需要进行调整操作的数值的下标/一个数组&#xff08;完全二叉树&#xff09;堆元素个数需要调整操作的数值的下标。实际上就是对完全二叉树当中的某一点…...

Lua require 函数使用

从 Lua 的用户文档中我们知道 require("modName") 函数是用来加载模块的&#xff0c;而如果这个modName已经用require 加载过的&#xff0c;再调用require时&#xff0c;将直接返回模块的值。因为函数首先查找 package.loaded 表&#xff0c; 检测 modName 是否被加载…...

【面试】如何定位线上问题?

这个面试题我在两年社招的时候遇到过&#xff0c;前几天面试也遇到了。我觉得我每一次都答得中规中矩&#xff0c;今天来梳理复盘下&#xff0c;下次又被问到的时候希望可以答得更好。 下一次我应该会按照这个思路去答&#xff1a; 1、如果线上出现了问题&#xff0c;我们更多…...

字节二面,原来我对自动化测试的理解太浅了

如果你入职一家新的公司&#xff0c;领导让你开展自动化测试&#xff0c;作为一个新人&#xff0c;你肯定会手忙脚乱&#xff0c;你会如何落地自动化测试呢&#xff1f; 01 什么是自动化 有很多人做了很长时间的自动化但却连自动化的概念都不清楚&#xff0c;这样的人也是很悲…...

Android11.0 应用升级成功后立即断电重启,版本恢复

问题&#xff1a;客户反馈内置的应用升级成功后立刻断电重启&#xff0c;应用的版本被恢复。 使用adb命令升级客户应用&#xff0c;查看版本显示已更新&#xff0c;/data/system目录下packages.xml和packages.xml中应用版本信息均已更新 C:\Users\dell>adb shell dumpsys …...

关于python常用软件用法:Pycharm 常用功能

人生苦短&#xff0c;我用python 一.Pycharm的基本使用 1.在Pycharm下为你的Python项目配置Python解释器 &#xff08;1&#xff09;.Setting>Project Interpreter>源码资料电子书:点击此处跳转文末名片获取 二.在Pycharm下创建Python文件、Python模块 1.File>New&g…...

SOLIDWORKS你不知道的小技巧

◉ SOLIDWORKS圆弧长度标注点智能标注&#xff0c;再选中该圆弧&#xff0c;然后分别点圆弧的两个端点&#xff0c;点击左键可以标注圆弧长度。◉ SOLIDWORKS强力裁剪剪裁实体中的强劲剪裁&#xff0c;除了可以裁剪实体外&#xff0c;还可以任意延伸实体。◉ SOLIDWORKS转折线转…...

有了HTTP,为啥还要用RPC

既然有 HTTP 请求&#xff0c;为什么还要用 RPC 调用&#xff1f; 一直以来都没有深究过RPC和HTTP的区别&#xff0c;不都是写一个服务然后在客户端调用么&#xff1f; HTTP和RPC最本质的区别&#xff0c;就是 RPC 主要是基于 TCP/IP 协议的&#xff0c;而 HTTP 服务主要是基…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...