g ++不编译某些嵌套模板

And*_*w A 3 c++ templates nested

当定义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
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 6

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

tmp2 = tmp.template alloc_B<U>( );
Run Code Online (Sandbox Code Playgroud)

这就是问题,这就是为什么它在你使用时有效A<int>,因为类型不再依赖于模板参数U.


Yuu*_*shi 5

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

tmp2 = tmp.template alloc_B<U>( );
Run Code Online (Sandbox Code Playgroud)