只是为了提供一些背景知识template
需要关键字:
template<typename T>
int do_outer(T& val)
{
int i;
val.get_inner().get<int>(i);
return i;
}
当编译器看到这个函数时,它不知道它的类型是什么val
是。因此它解析该行val.get_inner().get(i)
如下:
1: val .
编译器看到.
因此可以假设“val”具有类类型,并且下一个标识符是成员对象或函数的名称。
2. val . get_inner (
get_inner
是成员的名称,然后编译器会看到(
。唯一的可能就是get_inner
是一个函数名,所以这是一个函数调用。然后它解析参数,直到找到结束)
.
3. val . get_inner () .
至于第一步,它现在知道 get_inner 返回的值必须是类类型,因此它知道下一个标识符是成员对象或函数。
4. val . get_inner () . get <
那么,什么可以<
可能意味着?当然,它是模板参数的开始......或者也许它是小于运算符?
我们知道get
只能是一个对象或一个函数。如果它是一个对象那么<
作为小于运算符非常有意义。此外,该标准或多或少规定,只有在名称之前<
is a template-name
它会治疗<
作为模板参数(14.2/3):
在名称查找(3.4)之后发现一个名称是一个模板名称,如果这个名称后面跟着一个<
, the <
始终被视为模板参数列表的开头,而永远不会被视为后跟小于运算符的名称。
在这种情况下,编译器不知道表达式的类型是什么val.get_inner()
是,所以它无法查找get
。它或多或少地假设它是一个成员对象而不是模板名称。 'get小于int
- 因此出现错误。
那么,为什么这些修复有效呢?
添加template
keyword
从字面上看,我们告诉编译器get
是一个模板名称,所以<
运算符被视为模板参数列表的开始。
删除模板参数
当 do_outer 没有模板参数时,即:val . get_inner () . get (
编译器期望该成员get
是一个对象或函数。这(
消除两者之间的歧义,并且名称被视为函数。稍后的模板参数推导将计算出模板参数的类型。