C++模板基础(一)
函数模板(一)
● 使用 template 关键字引入模板: template void fun(T) {…}
– 函数模板的声明与定义
– typename 关键字可以替换为 class ,含义相同
– 函数模板中包含了两对参数:函数形参 / 实参;模板形参 / 实参
● 函数模板的显式实例化: fun(3)
//函数模板的声明
template<typename T>
void fun(T);
//函数模板的再次声明
template<typename T>
void fun(T);
//函数模板的定义
template<typename T> //T为模板形参
//也可以写成template<class T>,但不能写成template<struct T>
void fun(T input) //input是函数形参
{std::cout << "template<typename T> void fun(T input): " << input << std::endl;
}
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);fun<int>(3);fun<double>(3);return a.exec();
}
函数模板被实例化成
#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun<int>(int input)
{std::operator<<(std::cout, "template<typename T> void fun(T input): ").operator<<(input).operator<<(std::endl);
}
#endif#ifdef INSIGHTS_USE_TEMPLATE
template<>
void fun<double>(double input)
{std::operator<<(std::cout, "template<typename T> void fun(T input): ").operator<<(input).operator<<(std::endl);
}
#endif
– 实例化会使得编译器产生相应的函数(函数模板并非函数,不能调用)
– 编译期的两阶段处理
● 模板语法检查
● 模板实例化
– 模板必须在实例化时可见 :翻译单元的一处定义原则
//header.h
#include<iostream>
template<typename T>//在source.cpp翻译单元出现了一次,在main.cpp翻译单元也出现了一次,虽然链接时产生重定义,由于模板的两阶段处理的关系,标准放松了这个限制,翻译单元级别的一处定义原则
void fun(T input)
{std::cout << "template<typename T> void fun(T input): " << input << std::endl;
}
void normalFun() //普通函数发生链接错误,在source.cpp翻译单元出现了一次,在main.cpp翻译单元也出现了一次,链接时产生重定义,程序级别的一处定义原则
{//do something
}
inline void normalFun2() //inline关键字使得程序级别的一处定义原则退化成翻译单元级别的一处定义原则
{//do something
}
//source.cpp
#include<header.h>
void g()
{fun<float>(3);
}
//main.cpp
#include<header.h>
int main(int argc, char *argv[])
{fun<int>(3);fun<double>(3);return 0;
}
– 注意与内联函数的异同
相同点:都满足翻译单元级别的一处定义原则。
异同点:函数模板的翻译单元级别的一处定义原则的原因是为了保证编译期的两阶段处理;内联函数的翻译单元级别的一处定义原则的原因是在编译期,在被调用处可以拿来展开
template<typename T>
inline void fun(T input) //和template<typename T> void fun(T input)是两个概念,inline关键字使得在调用处展开
{std::cout << "template<typename T> void fun(T input): " << input << std::endl;
}
● 函数模板的重载
template<typename T>
void fun(T input)
{std::cout << "template<typename T> void fun(T input): " << input << std::endl;
}template<typename T>
void fun(T* input) //重载1
{std::cout << "template<typename T> void fun(T* input): " << *input << std::endl;
}template<typename T, typename T2>
void fun(T input, T2 input2) //重载2
{std::cout << "template<typename T, typename T2> void fun(T input, T2 input2): " << input << input2 << std::endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int x = 3;fun<int>(x); //调用template<typename T> void fun(T input)fun<int>(&x); //调用template<typename T> void fun(T* input)return a.exec();
}
参考
深蓝学院:C++基础与深度解析