【发布时间】:2016-01-09 17:03:31
【问题描述】:
考虑以下代码:
struct bar
{
template <typename U>
void fun0() const {}
};
template <typename T>
struct foo
{
void
fun1(const bar& d)
{
// (1) KO
fun2(d).fun0<int>();
// (2) OK
fun2(d).template fun0<int>();
// (3) OK
d.fun0<int>();
}
bar
fun2(const bar& d)
{
return d;
}
};
第 (2) 和 (3) 行编译,但 (1) 失败:
error: use 'template' keyword to treat 'fun0' as a dependent template name
fun2(d).fun0<int>();
^
template
(正如预期的那样,如果foo 不再是模板结构,(1)也会编译)
这里为什么bar::fun0 是一个依赖模板名? bar 不依赖于foo 的模板参数T。
编辑:
显然,bar::fun2 负责 .template 处理的歧义。例如,让我们添加以下 2 个免费函数:
bar
fun3(const bar& d)
{
return d;
}
template <typename T>
T
fun4(const T& d)
{
return d;
}
fun3(d).fun0<int>() 和fun4(d).fun0<int>()) 也在foo::fun1 的上下文中编译。所以歧义是由foo的模板参数引起的。
为什么fun2(d).fun0<int>() 不被解析为对成员函数模板的调用?
【问题讨论】:
-
因为您可能会专门化
fun2以返回除bar以外的其他内容。 -
@AlanStokes 您将如何专门化
fun2以允许更改返回类型,但仍保留fun1? -
@AlanStokes 你只能专门化
fun2来返回一个协变类型(所以它必须是从bar派生的),所以保证协变类型具有相同的功能(即它必须具有template <typename> void fun0() const函数)。所以它总是会返回一个实际上是bar的类型 -
@AlanStokes 你不能返回
baz。fun2已声明为返回bar。您需要专门化整个模板,而不仅仅是成员,以允许返回类型不同,并且在专门化整个模板时,fun1不会被保留。 -
这适用于虚函数的覆盖,这里不相关。
标签: c++ templates language-lawyer