我的C ++代码如下:
//test.cpp
#include <iostream>
using namespace std;
template <int SIZE, class T>
struct A
{
void g(int x, const T& t)
{
t.f<SIZE>(x);
}
};
struct B
{
template <int SIZE>
void f(int x) const
{
cout << SIZE << ": " << x << endl;
}
};
int main(void)
{
A<3, B> a;
B b;
a.g(9, b);
return 0;
}
使用g ++编译时出现了一个令人惊讶的错误(版本为4.8.2
):
test.cpp: In instantiation of ‘void A<SIZE, T>::g(int, const T&) [with int SIZE = 3; T = B]’:
test.cpp:27:13: required from here
test.cpp:9:12: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
t.f<SIZE>(x);
^
为什么将<
作为operator<
而不是标记来包含模板参数?
答案 0 :(得分:7)
因为代码本质上是模糊的 1 所以编译器必须决定哪种方式。并且C ++标准委员会任意决定如果有疑问,假设名称是变量,而不是类型。
如果您希望将代码解析为模板,则需要明确说明:
t.template f<SIZE>(x);
1 在解析此代码时,t
的类型尚不清楚,因为它是一个模板。请考虑以下类型:
struct T {
int f;
};
如果您现在使用该类型实例化A
,则会获得(自模板实例化以来的伪代码):
void A<3, T>::g(int x, T const& t) {
((t.f) < 3) > x;
}
我添加了括号以便澄清:这是编译器看到你的代码的方式,它完全有效(虽然没有意义)。
答案 1 :(得分:4)
让我们来看看:
t.f < SIZE > (x);
空白并不重要。如果t.f
是变量,则可以说:t.f < SIZE
然后执行(结果)> x
。
此外,编译器还不知道t.f
是变量还是函数模板。请记住,模板可以是专用的,因此即使t.f
似乎是一个函数模板,也是如此;稍后在这篇文章中,这段代码可以从B
的特化中实例化,其中t.f
是一个变量。
要解决这个难题,将含糊不清的名称视为变量名,除非您明确指出它们是其他内容。在这种情况下,通过写t.template f
来完成;当typename T::iterator
是一个从属名称时,类似的原则让我们写T
。