2013-04-05 75 views
3

定义BREAK时,g ++ 4.7.2不会编译以下内容,我认为这是有效的C++。如果A<U> tmp更改为其他内容(例如A<int> tmp),它会在BREAK定义的情况下进行编译 - 但这使得此处的最小测试用例可以正常工作,但在我的实际应用程序中并不好。这里有什么不合法的C++吗?g ++不编译某些嵌套模板

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 
} 

回答

6

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

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

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

5

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

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