我有一些 C++ 代码,如果没有 -fpermissive 选项,就无法再编译。
这是我无法分享的专有代码,但我认为我已经能够提取一个简单的测试用例来演示该问题。这是 g++ 的输出
template_eg.cpp: In instantiation of 'void Special_List<T>::do_other_stuff(T*) [with T = int]':
template_eg.cpp:27:35: required from here
template_eg.cpp:18:25: error: 'next' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
template_eg.cpp:18:25: note: declarations in dependent base 'List<int>' are not found by unqualified lookup
template_eg.cpp:18:25: note: use 'this->next' instead
所以这是产生问题的代码:
template<class T> class List
{
public:
void next(T*){
cout<<"Doing some stuff"<<endl;
}
};
template<class T> class Special_List: public List<T>
{
public:
void do_other_stuff(T* item){
next(item);
}
};
int main(int argc, char *argv[])
{
Special_List<int> b;
int test_int = 3;
b.do_other_stuff(&test_int);
}
我并不是想找出如何修复代码以使其再次编译。
只需将 next(item) 更改为 this->next(item) 即可
我试图更好地理解为什么这种改变是必要的。
我在这个页面找到了解释:http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html虽然这个解释很有用,但我仍然有一些问题。我的函数采用 T* (指向类型 T 的指针)这一事实不应该使其依赖于模板参数吗?
用我自己的措辞来说,编译器(gcc 4.7)不应该能够找出 next() 函数在基类 List 中吗?
为什么有必要在每个此类调用之前添加 this-> ?
我注意到 clang 3.1 表现出相同的行为,因此我假设 c++ 标准中有一些要求需要这种行为。有人能提供理由吗?
问题是模板分两次处理(根据标准,VS 则不然)。在第一遍中,在类型替换之前,将查找并检查所有不依赖于模板参数的内容。一旦类型被替换,从属名称就会在第二遍中解析。
现在,在第一遍中没有任何迹象表明next
依赖于模板参数,因此需要解析类型替换之前。现在,因为基本类型是在当前模板的模板参数上模板化的,所以编译器无法查看它(它可能专门用于某些类型,并且不知道什么类型T
我们正在实例化模板,我们不知道要使用哪个专业化,即基础depends on T
我们正在检查之前知道T
).
添加的技巧this->
turns next
到从属名称中,这又意味着查找被延迟到第二遍,其中T
是已知的,并且因为T
已知,List<T>
也是已知的并且可以查到。
EDIT:上面答案的措辞中缺少的一个重要细节是第二阶段查找(类型替换之后)只会添加在参数相关查找期间找到的函数。也就是说,如果next
是与关联的命名空间中的自由函数T
它会被发现,但它是基地的成员,对于 ADL 来说是不可见的T
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)