3

定义 BREAK 时,g++ 4.7.2 不会编译以下内容,我认为这是有效的 C++。A<U> tmp如果将其更改为其他内容,它确实会使用定义的 BREAK 进行编译,例如A<int> tmp- 虽然这使得这里的最小测试用例可以工作,但在我的实际应用程序中并不好。这里有什么不是合法的 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
}
4

2 回答 2

6

alloc_B函数模板是一个从属名称。你必须这样称呼它:

tmp2 = tmp.template alloc_B<U>( );

这就是问题所在,这就是为什么它在您使用时起作用的原因A<int>,因为类型不再依赖于模板参数U

于 2013-04-05T01:16:06.530 回答
5

这是由于C++令人讨厌的解析规则之一。当它看到 时tmp.alloc_B<U>,这不会被解释为模板,而是tmp.alloc_B < U. 要解决此问题,您需要明确指定这是一个模板:

tmp2 = tmp.template alloc_B<U>( );
于 2013-04-05T01:18:32.723 回答