简写函数模板是C++20引入的一个新特性,是一个非常实用的语法糖。
在简写之前,自然是有完整语法的,让我们先来复习一下声明函数模板的完整语法:
1 | template<class T1, class T2> |
要声明一个函数模板,首先是template
关键字,后随一对尖括号括起来的模板形参列表。接下来的部分就和普通的函数声明语法一样了,并且模板形参列表中引入的名字,可以作为类型名用在函数声明中。
用模板形参来模板化函数形参是最常见的函数模板用法。并且,由于模板实参推导的存在,在使用这些函数模板时,不必显式的写出模板实参。
1 | // 推导出 T1 = int,T2 = double |
模板实参推导是使用函数模板时的便利特性,为了简化函数模板的声明,C++20引入了简写函数模板的语法:
1 | // 虽然看起来是个函数声明,但这实际上是个函数模板声明 |
这个简写的形式与上方的完整语法完全等价。简而言之,如果函数声明的形参列表中出现了auto
占位符类型,那么这个函数声明会声明一个函数模板,并且每一个auto
占位符都会为这个函数模板追加一个虚设的模板形参。
这些以auto
占位符声明的形参同样可以添加各种限定符和修饰符,例如cv限定、引用修饰符、指针修饰符等。
1 | //这两个foo的声明等价 |
形参包也可以简写:
1 | //这两个foo的声明等价 |
总而言之,将常规函数模板声明的函数形参列表中的类型名换成auto
即可。当然,只有函数形参列表中出现的auto
有这个效果,函数的类型说明符、尾随返回类型、或者函数体中的auto
还是原来的意思,即让编译器推导实际类型。
如果需要模板化函数的其他部分,还是要显式地写出模板形参列表。此外,简写函数模板也只对类型模板形参有效,非类型模板实参或者模板模板形参也不能简写。
1 | // 模板化返回类型,必须写出模板形参列表 |
简写函数模板的auto
占位符可以受概念制约:
1 |
|
简写函数模板版同样可以特化:
1 | template<> |
总体而言,这是一个很实用的语法糖,在仅需模板化函数参数列表时能够简化很多代码。实际上这也不能完全称得上新特性,它来自C++14就有的泛型lambda表达式,现在C++20终于将它扩展到了函数。
1 | // C++14: 泛型lambda |