簡體   English   中英

當非限定名稱查找涉及using-directives時,解釋[basic.scope.hiding] p2

[英]Interpretation of [basic.scope.hiding]p2 when unqualified name lookup involves using-directives

在c ++中有兩種類型的名稱隱藏:

1)正常名稱隱藏:[basic.scope.hiding] p1( http://eel.is/c++draft/basic.scope.hiding#1 ):

名稱可以通過嵌套聲明性區域或派生類([class.member.lookup])中相同名稱的顯式聲明來隱藏。

2)隱藏在[basic.scope.hiding] p2中的特殊名稱類型( http://eel.is/c++draft/basic.scope.hiding#2 ):

類名([class.name])或枚舉名稱([dcl.enum])可以由在同一范圍內聲明的變量,數據成員,函數或枚舉器的名稱隱藏。 如果類或枚舉名稱和變量,數據成員,函數或枚舉器在同一作用域(按任何順序)中聲明具有相同名稱,則類或枚舉名稱將隱藏在變量,數據成員,函數或枚舉器名稱可見。

我很想知道在執行非限定名稱查找時,名稱隱藏如何與using-directives交互。

對於隱藏行為的第一種類型的名稱是非常清楚的。 這是因為[basic.scope.hiding] p1已按照[basic.lookup.unqual]( http://eel.is/c++draft/basic.lookup.unqual )一節中的規則重新制定。

第二種類型的名稱隱藏沒有做同樣的事情。 所以現在出現以下問題:

*)第二種類型的名稱隱藏如何與涉及using-directives的非限定名稱查找交互?

在標准的其他地方尋找[namespace.udir] p2( http://eel.is/c++draft/namespace.udir#2 ),我認為這是回答這個問題的關鍵:

using-directive指定指定命名空間中的名稱可以在using-directive出現在using-directive之后的范圍內使用。 在非限定名稱查找([basic.lookup.unqual])期間,名稱看起來好像是在最近的封閉命名空間中聲明的,其中包含using-directive和指定的命名空間。 [注意:在此上下文中,“包含”表示“直接或間接包含”。 - 結束說明]

將此規則的as部分應用於[basic.scope.hiding] p1,使其與[basic.lookup.unqual]部分中的規則保持一致。 這個應用程序也與[basic.scope.hiding] p4( http://eel.is/c++draft/basic.scope.hiding#4 )一致。所以這看起來很有希望。

因此我認為我們可以通過類似地將[namespace.udir] p2的if部分應用到[basic.scope.hiding] p2來回答問題*)。 此應用程序也與[basic.scope.hiding] p4一致。 我認為這也是對c ++標准最自然,最簡單的解釋。

然而問題是Clang和GCC沒有和我做同樣的解釋。 例如:

namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;    
int main() { sizeof(i); }

根據我的解釋,這個程序應該是格式良好的, i應該被查找為整數變量。 Clang和GCC都不同意這一點,因為它給名字查找含糊不清。

在Clang的情況下,這種更復雜的解釋會導致以下錯誤:

namespace N { static int i = 1; }
namespace M { struct i {}; }
namespace P {
    using N::i;
    using M::i;
}
namespace Q { using M::i; }
using namespace P;
using namespace Q;
int main() { sizeof (i); }

沒有錯誤,但改變

using namespace P;
using namespace Q;

using namespace Q;
using namespace P;

我們得到名稱查找歧義錯誤。 GCC在這里至少是一致的。

我是否正確地解釋了c ++標准?

我相信這里的關鍵詞是:

名稱可以通過嵌套聲明性區域或派生類(10.2)中相同名稱的顯式聲明來隱藏。

類名(9.1)或枚舉名(7.2)可以通過在同一范圍內聲明的變量,數據成員,函數或枚舉器的名稱隱藏。

在這個例子中:

namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;    
int main() { sizeof(i); }

無論i S IN不同,非嵌套范圍中聲明,所以沒有隱藏。 名稱查找將它們視為::中聲明它們,但這不是隱藏規則所規定的。

否則,我們有[basic.lookup]:

名稱查找應找到名稱的明確聲明(見10.2)。 如果名稱查找名稱是函數名稱,則名稱查找可以將多個聲明與名稱相關聯;

::沒有明確的聲明,因此這段代碼格式錯誤且錯誤是正確的。 對於另一個例子也是如此,因此有一些使用聲明排序的事實,clang編譯它是一個錯誤。

雖然這是非規范性的,但[namespace.udir]中有一個例子可以解釋清楚:

[注意:特別是,變量,函數或枚舉的名稱不會隱藏在不同命名空間中聲明的類或枚舉的名稱。 例如,

 namespace A { class X { }; extern "C" int g(); extern "C++" int h(); } namespace B { void X(int); extern "C" int g(); extern "C++" int h(int); } using namespace A; using namespace B; void f() { X(1); // error: name X found in two namespaces g(); // OK: name g refers to the same entity h(); // OK: overload resolution selects A::h } 

- 尾注]

namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;    
int main() { sizeof(i); }

這是不正確的。 §7.3.4/ 6:

如果名稱查找在兩個不同的名稱空間中找到名稱的聲明,並且聲明不聲明相同的實體並且不聲明函數,則名稱的使用是錯誤的。

這同樣適用於您的第二個示例。 請注意,例如,適用於名稱隱藏規則

struct A {} A;

......沒有你的情況下適用,因為這兩個i s的在不同的范圍聲明。 也,

在非限定名稱查找([basic.lookup.unqual])期間,名稱看起來好像是在最近的封閉命名空間中聲明的,其中包含using-directive和指定的命名空間。

也是無關緊要的,因為名稱查找產生的任何歧義,如在你的i的例子中, 在查找之后處理 - 在例如前面提到的§7.3.4/ 6中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM