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

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


http://www.kler.cn/a/5473.html

相关文章:

  • 学习C++:数组
  • 办公 三之 Excel 数据限定录入与格式变换
  • kubernetes学习-kubectl命令、探针(二)
  • OpenLinkSaas使用手册-待办事项和通知中心
  • Redis的生态系统和社区支持
  • 物理知识1——电流
  • 有了Bug,先看看类型
  • Activation Function激活函数
  • 三极管用作开关电路的一些思考
  • 跟着AI学AI(1): 线性回归模型
  • 如何使用Spring+OpenAI生成图像
  • 多传感器融合定位GNSS、IMU、Lidar、Camera
  • 06 Laplacian算法
  • HTML5 SSE
  • 数据结构和算法(3):递归
  • 程序员万万不能去的3种公司,越做越倒退,过来人的经验
  • VerilogHDL基本语法和程序
  • PCB模块化设计24——DCDC电源模块PCB布局布线设计规范
  • python Format()函数的用法___实例详解(一)(全,例多)___各种格式化替换,format对齐打印
  • WTI原油交易价格(1986年1⽉2⽇-2022年9⽉6⽇)
  • (数字图像处理MATLAB+Python)第三章图像基本运算-第一节:图像几何变换
  • 卷麻了,00后测试用例写的比我还好,简直无地自容.....
  • ChatGPT +工业机器人/自动驾驶控制器的一些尝试
  • 【bugdebug】为什么表名没有输入错误,数据库连接也连上了,但一查询还是显示对象名“XXX”无效?
  • Input子系统剖析
  • Huggingface微调BART的代码示例:WMT16数据集训练新的标记进行翻译