問題描述
我有一些 C++ 代碼在沒有 -fpermissive 選項的情況下不再編譯.這是我無法共享的專有代碼,但我認為我已經能夠提取一個簡單的測試用例來演示問題.這是 g++ 的輸出
I have some C++ code that is no longer compiling without the -fpermissive option. It's propriety code that I can't share, but I've think I've been able to extract a simple test case that demonstrates the problem. Here is the output from 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
這里是產生問題的代碼:
So here is the code the generates the problem:
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雖然這個解釋很有用,但我仍然有一些問題.我的函數采用 T*(指向類型 T 的指針)這一事實不應該使它依賴于模板參數.用我自己的話來說,編譯器(gcc 4.7)不應該能夠確定 next() 函數在基類 List 中嗎?為什么有必要在每個這樣的調用前加上 this-> ?我注意到 clang 3.1 表現出相同的行為,所以我假設 c++ 標準中有一些要求需要這種行為.任何人都可以提供理由嗎?
I am not trying to find out how to fix the code to make it compile again. That's simply a matter of changing next(item) to this->next(item) I'm trying to better understand why this change is necessary. I found an explanation on this page: http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html While that explanation was useful, I still have some questions. Shouldn't the fact that my function takes a T* (pointer to type T) make it dependent on the template argument. In my own wording, shouldn't the compiler (gcc 4.7) be able to figure out that the next() function is in the base class List? Why is it necessary to prepend this-> in front of every such call? I've notice that clang 3.1 exhibits the same behavior, so I assume that there is some requirement in the c++ standard that requires this behavior. Could anyone provide a justification for it?
推薦答案
問題是模板是分兩遍處理的(按照標準,VS 不然).在第一遍中,在類型替換之前,查找并檢查所有不依賴于模板參數的內容.一旦類型被替換,從屬名稱就會在第二次傳遞中被解析.
The problem is that templates are processed in two passes (according to the standard, VS does otherwise). In the first pass, before the type substitution, everything that does not depend on the template arguments is looked up and checked. Dependent names are then left to resolve in the second pass, once the type has been substituted.
現在,在第一遍中沒有任何內容表明next
依賴于模板參數,因此它需要在類型替換之前解析.現在,因為基本類型是在當前模板的模板參數上模板化的,編譯器無法查看它(它可能專門用于某些類型,并且不知道我們正在實例化模板的類型 T
與,我們不知道使用哪個專業化,即基礎 depends 在 T
上,我們在知道 T
之前正在檢查).
Now, in the first pass there is nothing that indicates that next
is dependent on template arguments, and thus it needs to resolve before type substitution. Now, because the base type is templated on the template argument of your current template, the compiler cannot look into it (it might be specialized for some types, and without knowing what type T
we are instantiating the template with, we cannot know which specialization to use, i.e. the base depends on T
and we are checking before knowing T
).
添加 this->
的技巧將 next
變成了依賴名稱,這反過來意味著查找被延遲到第二遍,其中 T
是已知的,因為 T
是已知的,所以 List
也是已知的,可以查詢.
The trick of adding this->
turns next
into a dependent name, and that in turn means that lookup is delayed until the second pass, where T
is known, and because T
is known, List<T>
is also known and can be looked up into.
EDIT:上述答案的措辭中缺少的一個重要細節是第二階段查找(在類型替換之后)只會添加在參數相關查找期間找到的函數.也就是說,如果 next
是與 T
關聯的命名空間中的自由函數,它將被找到,但它是基礎上的成員,對于 ADL 上的 ADL 不可見T
.
EDIT: One important detail missing in the wording of the answer above is that second phase lookup (after type substitution) will only add functions found during argument dependent lookup. That is, if next
was a free function in a namespace associated with T
it would be found, but it is a member on the base, which is not visible for ADL on T
.
這篇關于C++ 模板中的名稱查找的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!