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