2013-01-16 29 views
12

這是編譯器錯誤嗎?名稱空間域中的操作符在全局範圍內隱藏另一個

template <typename T> 
T& operator++(T& t) 
{ 
    return t; 
} 

namespace asdf { 

enum Foo { }; 
enum Bar { }; 

Foo& operator++(Foo& foo); 

void fun() 
{ 
    Bar bar; 
    ++bar; 
} 

} // end namespace asdf 

int main() 
{ 
    return 0; 
} 

的GCC 4.7的錯誤消息是:

Foo& operator++(Foo& foo); 
+1

[是的是](http://liveworkspace.org/code/2vreOi$0).... –

+3

不這樣認爲。 VC++生成相同的。 – SChepurin

+1

@KarthikT:我不確定你的鏈接代碼是如何支持「是一個bug」的 - 參數。 –

回答

13

沒有這不是一個錯誤:

error: no match for 'operator++' in '++bar' 
note: candidate is: 
note: asdf::Foo& asdf::operator++(asdf::Foo&) 
note: no known conversion for argument 1 from 'asdf::Bar' to 'asdf::Foo&' 

,如果你註釋掉編譯。有三套平行的運營商考慮。會員,非會員運營商和內置。

通過普通的不合格+ ADL查找,忽略所有類成員函數,查找非成員函數。因此,全局運算符被一個更緊密的詞彙隱藏起來(並且中介成員函數不會隱藏其他非成員)。

請注意,重載決議發生後名稱查詢;在你的情況下,名稱operator++被發現,但沒有適當的超載。

如果酒吧已被全局聲明,和/或在命名空間ASDF另算,ADL(在前者的情況下)或普通不合格查找(在後一種情況下)將在已經拖了運營商。


Overload resolution (...) takes place after name lookup has succeeded.(C++標準)

+0

我不確定這是否足夠詳細。如果不匹配,請不要查找下一個封閉名稱空間? –

+1

@phresnel:但是,'operator ++'這個名字怎麼形成'operator ++'的不匹配?它只是名稱查找期間相關的*名稱*。 –

+0

@phresnel,實際上也是本地聲明。將更新... –

7

沒有,這不是一個編譯錯誤。

對於表達式++bar有兩種名稱查找方式。

  • 常規名稱查找搜索封閉範圍和命名空間,直到找到的operator++第一 occurence。這個搜索從頭到尾都在進行,因此全局名稱空間最後被搜索。在查找運算符函數時,會員函數被分別處理(並且不停止該搜索)。
  • 依賴於參數的查找將在下一個腳本中進行搜索並搜索其他類和名稱空間,但只會查找與該函數的參數(本例中爲operator++)相關的那些。

在問題的示例中,正常查找找到asdf::operator++並停止查找。
依賴於參數的查找僅將asdf名稱空間添加到要搜索的位置,因爲這是enum Bar的關聯名稱空間。因此,找不到全球operator++

您可以使用名稱空間asdf中的使用聲明找到全局operator++

+0

您描述的第一個項目符號不考慮類作用域。也就是說,即使在類成員函數中使用了運算符表達式,即使存在具有相同名稱的成員運算符,也可以找到命名空間範圍運算符(即使在非addad相關的命名空間範圍中)。 –

+0

@ JohannesSchaub-litb:這是C++ 03和C++ 11之間的變化嗎?因爲我在C++ 03第3.4.1節[basic.lookup.unqual]中找不到這樣的異常。 –

+1

規則在13.3.1.2中規定:-) –

1

超載僅適用於在同一範圍中定義的名稱。一旦編譯器找到匹配的名稱,它就不會在外部作用域中查找,即使找到的名稱適用於某些無法使用的名稱。這與操作員無關;如果代碼使用函數名稱的方式與使用operator ++相同,則會得到相同的錯誤。例如:

void f(int); 

struct C { 
void f(const C&); 
void g() { 
    f(3); // error: f(const C&) can't be called with argument 3 
}; 
相關問題