函数模板
函数模板的定义和声明
1. 定义:
template
void fun(T input)
{
...
}
//或
template
void fun(T input)
{
...
}
2. 声明
template
void fun(T input);
3. 要点
- 函数模板不是函数,不能直接调用,在编译期编译期对其进行实例化产生相应的函数才能调用
- 两对形参实参,fun(3) int:模板实参,3:函数实参,T:模板形参,input:函数形参
- 编译器对函数模板的两阶段处理:1. 模板语法检查(简略的检查) 2. 模板实例化后检查(再次检查)
- 由于需要在编译期进行模板实例化,故C++里规定模板函数为翻译单元级一处定义(每个源文件中可包含相同的函数模板定义)。注意:将函数模板设置为翻译单元级一处定义是为了编译期进行实例化操作,这点与内联函数不同
补充:
内联函数,在头文件中定义函数用内联函数,类内定义的函数会自动引入内联,在调用(准确 的说应该是使用)内联函数时,会直接将函数展开到调用的地方,减小调用成本,但函数较长时不适用。
函数调用时需要保存当前状态,复制实参,返回时恢复原状态,相对来讲成本较高,引入内联函数降低调用成本,由于需要将函数展开,故内联函数为翻译单元级一处定义。
函数模板的特性
1. 函数模板可重载
template
void fun(T1 input1,T2 input2)
{
...
}
template
void fun(T input)
{
...
}
2. 模板实参的类型推导
函数模板在实例化时没有显示提供模板实参,这时系统会尝试对模板实参进行推导,推导的原则与auto相似 1. 函数形参是左值引用或指针
忽略表达式类型中的引用,将表达式类型与函数形参进行模式匹配推导出模板实参。
template
void fun(T& input)
{
...
}
int main()
{
int x=2;
int& y=x;
fun(y); //int&-->int T& =int --> T=int
fun(x); //int去引用还是int T&=int --> T=int
}
- 函数形参是万能引用
template
void fun(T&& input)
{
...
}
int main()
{
int x=3;
fun(x); //int 去引用还是 int T&&=int ---> T=int&(此时触发引用重叠int&&&=int&)
fun(4); //T&&=3 --> T=int
}
- 函数形参不包含引用
(1)忽略类型表达式的引用 (2)忽略顶层const (3)数组或函数转为相应指针
template
void fun(T input)
{
...
}
const int& x-->int
const int* const ptr-->const int*
int x[3] -->int*
注意:
- 模板实参不一定能够推导得到
template
void fun(T1 in1,T2 in2)
{
}
fun(3,5.0); //推导有歧义
template
in1 fun(T2 in2)
{
}
fun(3); //无法推导
//此时可增加缺省模板形参来解决
template
in1 fun(T2 in2)
{
}
fun(3); //解决问题
- 显式指定的模板实参必须从最左开始,依次指定
template
in1 fun(T2 in2)
{
}
fun(3) //T1=int
//可以显式指定部分模板实参,隐式推导其他模板实参,但得满足显示指定实参从最左开始,不可跳跃来显式指定
//因此尽量将需要显式指定的模板形参,在定义时放在左边
- 匹配失败不是错误(SFINAE)
匹配失败并不是模板的错误,而是找不到合适模板。
模板与非模板同时匹配,且匹配等级相同,优先选择非模板版本(特殊版本)
template
void fun(T1 in1,T2 in2)
{
}
template
void fun(T1 in1,float in2)
{
}
fun(2,3.5f); //此时系统会匹配void fun(T1 in1,float in2)
3. 模板实例化控制
例如fun(x),显式实例化时,包含实例化和调用两个过程,希望能够提前实例化,之后直接调用,提高性能。
template
void fun(T x)
{
}
template
void fun(int x); //定义,编译器会实例化函数模板
//但此时相当于引入了一个函数的定义,因此需要满足程序级一处定义原则,不可多处定义。
//若定义不在该翻译单元内部,则需要引入声明
extern template
void fun(int x);
4. 函数模板的特化
对特殊的模板引入特殊的算法,注意是对特例模板引入特殊算法,与函数重载不同。
template
void fun(T input)
{
}
template <>
void fun(int input)
{
}
注意:
- 函数模板不支持部分特化,特化版本的函数一定是以template <>开头。
- 函数特化比较复杂,稍微写错一点就会出现错误,因此尽量用函数重载来替代函数模板特化
template
void fun(T input)
{
}
void fun(int input)
{
}
5. C++20使用auto代替函数模板
void fun(auto x)
{
}
int main()
{
int x=3;
fun(3); //会被实例化为void fun(int x)
}
不能完全替代模板的作用,简单函数可以用。
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容