当前位置: 首页 > 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

http://www.lryc.cn/news/43912.html

相关文章:

  • pycharm使用记录
  • Linux命令·kill·killall
  • Linux /proc/version 文件解析
  • 【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)
  • STL容器之<array>
  • flask教程6:cookie和session
  • 【JavaEE初阶】第六节.网络原理TCP/IP协议
  • 模式识别 —— 第六章 支持向量机(SVM)与核(Kernel)
  • 总结 synchronized
  • 360周鸿祎又“开炮”:GPT 6-8就将产生自主意识!我们来测算一下对错
  • python——飞机大战小游戏
  • 数组(完全二叉树)向下建堆法与堆排序O(N*logN)
  • Lua require 函数使用
  • 【面试】如何定位线上问题?
  • 字节二面,原来我对自动化测试的理解太浅了
  • Android11.0 应用升级成功后立即断电重启,版本恢复
  • 关于python常用软件用法:Pycharm 常用功能
  • SOLIDWORKS你不知道的小技巧
  • 有了HTTP,为啥还要用RPC
  • [leetcode] 动态规划
  • 科大奥瑞物理实验——热电偶特性及其应用研究
  • Eclips快捷键大全(超详细)
  • 整懵了,蚂蚁金服4面成功拿下测开offer,涨薪10k,突然觉得跳槽也不是那么难
  • C++内存分布malloc-free-new-delete的区别和联系
  • 【华为OD机试 2023最新 】 最多颜色的车辆(C++ 100%)
  • Linux安全加固
  • Java基础学习(6)
  • 【LeetCode】链表练习 9 道题
  • 轴承远程监控系统解决方案
  • 阿里云轻量服务器Workbench root远程连接和一键连接的区别