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);
}
#endif


template
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);
}
#endif


template
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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python(白银时代)——文件操作

文件的基本操作 概念 在计算机中&#xff0c;文件是以 二进制 的方式保存在磁盘上的 文本文件 和 二进制文件 文本文件&#xff08;用记事本打开能直接能看懂的&#xff09; 可以使用 文本编辑软件查看 本质上还是二进制的,比如 Python的源码文件 二进制文件&#xff08;用…

并发编程(六)-AbstractExecutorService源码分析

一、AbstractExecutorService简介AbstractExecutorService是一个抽象类&#xff0c;实现了ExecutorService接口&#xff0c;提供了线程池的基本实现。它是Java Executor框架的核心类&#xff0c;提供了线程池的基本操作&#xff0c;如提交任务、管理线程池、执行任务等。自定义…

阻塞队列(BlockingQueue)的实现和使用

阻塞队列&#xff08;BlockingQueue&#xff09; 文章目录阻塞队列&#xff08;BlockingQueue&#xff09;阻塞队列的梗概解耦合和削峰填谷java代码实现一个阻塞队列阻塞队列的梗概 众所周知&#xff0c;队列是一种数据结构&#xff0c;符合先进先出的结构&#xff0c;先进先出…

【动态绘图】python可视化--丝滑版

✅作者简介&#xff1a;在读博士&#xff0c;伪程序媛&#xff0c;人工智能领域学习者&#xff0c;深耕机器学习&#xff0c;交叉学科实践者&#xff0c;周更前沿文章解读&#xff0c;提供科研小工具&#xff0c;分享科研经验&#xff0c;欢迎交流&#xff01;&#x1f4cc;个人…

鼎桥通信,拥抱基础创新的“高灵活性”时代

作者 | 曾响铃 文 | 响铃说 伴随数智化转型成为时代变革大方向&#xff0c;一批走在时代前端的数智化转型企业应运而生&#xff0c;不断丰富5G、物联网等新兴技术的应用场景&#xff0c;构建万智互联的产业生态。作为国内通信领域的引领者&#xff0c;鼎桥通信技术有限公司&a…

AF染料试剂Alexa fluor 680 PEG Biotin,AF680 PEG Biotin,荧光强度稳定利于多种荧光标记

文章关键词&#xff1a;AF染料试剂&#xff0c;AF680&#xff0c;PE-Biotin衍生物Alexa fluor 680 PEG Biotin&#xff0c;AF680 PEG Biotin | Alexa fluor 680-PEG-生物素| CAS&#xff1a;N/A | 纯度&#xff1a;95%试剂参数信息&#xff1a; CAS&#xff1a;N/A 外观&am…

docker使用

dokcer 安装 # 1、yum 包更新到最新 yum update # 2、安装需要的软件包&#xff0c; yum-util 提供yum-config-manager功能&#xff0c;另外两个是devicemapper驱动依赖的 yum install -y yum-utils device-mapper-persistent-data lvm2 # 3、 设置yum源 yum-config-manager …

精确性和准确性是两码事儿

准确性(Accuracy)是与正确答案的接近程度&#xff0c;精确性(Precision)是对这个答案的分辨率。 假设&#xff0c;你问我&#xff0c;”现在几点了?” 我抬头看看太阳&#xff0c;然后估算了一下&#xff0c;回答道 “现在是上午 10 点 35 分 22.131 秒” 我给出的是一个足…

Nacos配置中心优雅配置JSON数据格式

在我业务开发中&#xff0c;需要在配置中心配置Json数据&#xff0c;返回给前端。因Nacos默认不支持Json格式配置&#xff0c;需要搭配监听器获取配置中心Json数据&#xff0c;返回给客户端。二、搭配Nacos配置Josn数据1. bootstrap.ymlserver:port: 9000 spring:application:n…

Vue使用ElementUI对table的指定列进行合算

前言 最近有一个想法&#xff0c;就是记录自己花销的时候&#xff0c;table中有一项内容是花销的金额。然后想在table的底部有一项内容是该金额的总计。 然后我就顺着elementui的table组件寻找相关的demo&#xff0c;还真发现了一个这样的demo。 对于这个demo&#xff0c;官方…

SSH框架整合教程

工程目录结构如下&#xff1a; 本工程只介绍SSH整合的基本流程&#xff0c;所以没有写接口 1. 导入jar包 <dependencies><!--hibernate包--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId>…

【各种安装2】

各种安装2一、八阶段-第四章-案例导入说明1.安装MySQL1.1.准备目录1.2.运行命令1.3.修改配置1.4.重启2.导入SQL3.导入Demo工程3.1.分页查询商品3.2.新增商品3.3.修改商品3.4.修改库存3.5.删除商品3.6.根据id查询商品3.7.根据id查询库存3.8.启动4.导入商品查询页面4.1.运行nginx…

Linux线程同步与互斥(二)/生产消费者模型

⭐前言&#xff1a;本文会先后讲解生产消费者模型、条件变量和基于阻塞队列的生产消费者模型。 1.生产消费者模型 什么是生产消费者模型&#xff1f; 认识生产消费者模型 使用学生&#xff08;消费者&#xff09;&#xff0c;超市&#xff0c;供货商&#xff08;生产者&…

C++ 26 常用算法

目录 一、概述 1.1 常用遍历算法 1.1.1 算法简介 1.1.2 for_each遍历算法 1.1.3 transform遍历算法 1.2 常用查找算法 1.2.1 算法简介 1.2.2 find 查找算法 1.2.3 find_if 查找算法 1.2.4 adjacent_find 查找算法 1.2.5 binary_search 查找算法 1.2.6 count 查找算法…

【面试题】JS的一些优雅写法 reduce和map

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 JS的一些优雅写法 reduce 1、可以使用 reduce 方法来实现对象数组中根据某一key值求和 …

LFM雷达实现及USRP验证【章节3:连续雷达测距测速】

第一章介绍了在相对速度为0时候的雷达测距原理 目录 1. LFM测速 1.1 雷达测速原理 1.2 Chrip信号测速 2. LFM测速代码实现 参数设置 仿真图像 matlab源码 代码分析 第一章介绍了在相对速度为0时候的雷达测距原理&#xff0c;第二章介绍了基于LFM的雷达测距原理及其实现…

数据结构第十一期——线段树的原理和应用

目录 一、前言 二、线段树的概念 1、区间最值问题RMQ (Range Minimum/Maximum Query) &#xff08;1&#xff09;暴力法 &#xff08;2&#xff09;高效的办法&#xff1a;线段树 &#xff08;3&#xff09;把数列放在二叉树上 &#xff08;4&#xff09;查询最小值的复…

43-二叉树练习-LeetCode236二叉树的最近公共祖先

题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它…

一款全新的基于GPT4的Python神器,关键还免费

chartgpt大火之后&#xff0c;随之而来的就是一大类衍生物了。 然后&#xff0c;今天要给大家介绍的是一款基于GPT4的新一代辅助编程神器——Cursor。 它最值得介绍的地方在于它免费&#xff0c;我们可以直接利用它来辅助我们编程&#xff0c;真正做到事半功倍。 注意&#…

k8s实践 | configmapsecretpvpvc

文章目录configmap&secret&pv&pvc一、configMap1、应用场景2、创建configMap2.1、help文档2.2、使用目录创建2.3、根据文件创建2.4、文字创建2.5、直接方法2.6、pod中应用2.7、热更新二、secret1、Service Account2、opaque Secret2.1、创建示例2.2、使用方式三、k…