当定义BREAK时,g ++ 4.7.2将不编译以下内容,我认为这是有效的C ++。如果将A<U> tmp
更改为其他内容(例如A<int> tmp
),它会使用BREAK进行编译 - 虽然这使得最小测试用例在此处起作用,但在我的实际应用程序中并不好。这里有什么不合法的C ++吗?
template <typename T>
class B {
};
template <typename T>
class A {
public:
template <typename U> B<U> *alloc_B( );
};
template <typename T> template <typename U>
B<U> *A<T>::alloc_B( ) {
return new B<U>( );
}
#ifdef BREAK
template <typename T>
class C {
public:
template <typename U> void x(B<U> &b) {
A<U> tmp;
B<U> *tmp2;
tmp2 = tmp.alloc_B<U>( );
delete tmp2;
}
};
#endif
int main( ) {
A<int> a;
B<float> *bp = a.alloc_B<float>( );
delete bp;
#ifdef BREAK
C<int> c;
B<float> b;
c.x(b);
#endif
}
答案 0 :(得分:6)
alloc_B
函数模板是从属名称。你必须这样称呼它:
tmp2 = tmp.template alloc_B<U>( );
这就是问题所在,这就是为什么它在你使用A<int>
时有效,因为类型不再取决于模板参数U
。
答案 1 :(得分:5)
这是由于C++
令人烦恼的解析规则之一。当它看到tmp.alloc_B<U>
时,不会将其解释为模板,而是tmp.alloc_B < U
。要解决此问题,您需要明确指定这是一个模板:
tmp2 = tmp.template alloc_B<U>( );