模板学习中有些关键语法的使用方式难以理解,需要结合实际使用的场景进行记忆。今天看某篇模板使用要点总结的技术博客:
https://eli.thegreenplace.net/2011/04/22/c-template-syntax-patterns
个人觉得的很简要,而且也比较全面。但还是想将其中比较重要的点摘抄出来。
1. 依赖限定类型的去歧义
假如你有一个模板函数,在该模板函数体中实例化vector的iterator,类似如下代码:
template <class T>
string foo(vector<T> vec, ... other args)
{
vector<T>::iterator it = vec.begin();
}
该段代码在编译时是会报错的,原因在于iterator为依赖限定名称。在T的实际类型未确定之前,编译无法知道iterator是指代类型还是某个静态成员。消除歧义的方法很简单,显式注明iterator为类型名称,如下所示:
template <class T>
string foo(vector<T> vec, ... other args)
{
typename vector<T>::iterator it = vec.begin();
}
2. 显式指明限定成员使用去歧义
如:
class Foo
{
public:
template<class T> T member_func();
};
member_func是类Foo的成员函数,我们想通过隐式的类型限定符来调用该成员函数,如下:
template<class U> void func(U arg)
{
int obj = arg.member_func<int>();
}
此为无效的函数调用,因为编译器无法正确解析 arg.member_func<int>() 故而会将左侧尖括号解析为小于号,而认为member_func是arg某个非模板成员变量(也有可能arg恰好有该同名的成员变量,因其是模板函数,所以在未初始化之前是未知的)。
为了消除歧义,使用template关键字,如下:
template<class U> void func(U arg)
{
int obj = arg.template member_func<int>();
}
注意该语法同样适用于->和::符号。
博主有篇讲解完美转发和泛常引用的帖子讲的也很好,可以学习一下:Perfect forwarding and universal references in C++