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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值