4

A::クラス、テンプレート、列挙、または型定義を持たない翻訳単位でネストされた名前指定子が与えられた場合、整形式の場合、識別子Aは名前空間を参照する必要があります。

例えば:

namespace X
{
    int i;
}

int main()
{
    X::i = 42; // Here X:: is a nested-name-specifier
               // and X is a namespace-name
               // i is looked up qualified w.r.t. X
}

上記の例Aでは ですがX、私の質問は一般的なケースについてです。

の名前空間名の名前検索はどのようAに行われA::ますか?

名前検索の規則は 3.4 に要約されていますが、そのような状況でどのように (またはどの規則が) 適用されるかは明確ではありません。

たとえばA、修飾されていない名前のルックアップのルックアップですか? 3.4.1 は適用されますか?

別の言い方をすれば、 という名前の名前空間が検索される名前空間とAその順序は? 標準からこれをどのように結論付けましたか?

4

2 に答える 2

4

はい、A3.4.1 による通常の非修飾名ルックアップであり、ネストされた名前指定子を囲むスコープを連続して検索しますが、例外として、クラスと名前空間名のみが検出されます。たとえば、次のようになります。

int main()
{
    int X;
    X::i = 42; // OK, int X not found.
}

http://ideone.com/NaEIVd

実際にこの抜け穴を使用することはお勧めできません。Xクラス型のオブジェクトだったとしX::iたら、X.iまったく別のものになる可能性があります。


標準からこの結論に到達するには、3.4.3 (修飾ルックアップ、最終的に分析する高レベルの構造) から始めます。

クラスまたは名前空間のメンバーまたは列挙子の名前は、そのクラス、名前空間、または列挙を示す入れ子になった名前指定子に :: スコープ解決演算子 (5.1) を適用した後に参照できます。nested-name-specifier の :: スコープ解決演算子の前に decltype-specifier がない場合、:: の前にある名前の検索では、特殊化が型である名前空間、型、およびテンプレートのみが考慮されます。見つかった名前が名前空間、クラス、列挙、または依存型を指定していない場合、プログラムは不適切な形式です。

段落 2 を読むと、qualified-id が宣言されていないため、適用されません。残りの段落も同様に、適用できない例外を指定しています。では、 の前にあるものは何::ですか? 文法を参照してください。

nested-name-specifier:
    ::
    type-name ::
    namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier templateopt simple-template-id ::

アプリオリな基準にのみ一致しtype-name ::ます。namespace-name ::また、これらはこれまでに発見されたものと重複しています。type-nameまたはnamespace-name通常、特定のコンテキストでどのように解決されますか? 修飾されていないルックアップ。3.4.1 に進みます。

まず、3.4.1/1 は心に留めておくべき一般的な規則です。

3.4.1 にリストされているすべてのケースで、スコープは、それぞれのカテゴリのそれぞれにリストされている順序で宣言を検索されます。名前の検索は、名前の宣言が見つかるとすぐに終了します。宣言が見つからない場合、プログラムは不正な形式です。

次に該当する段落は 6 です。

名前空間 N のメンバーである関数の declarator-id に続く関数の定義で使用される名前 (ただし、説明の目的でのみ、N はグローバル スコープを表すことができます) は、ブロック内で使用する前に宣言する必要があります。それが使用されているか、それを囲むブロック (6.3) の 1 つで使用されているか、名前空間 N で使用する前に宣言するか、N がネストされた名前空間の場合は、N の囲んでいる名前空間の 1 つで使用する前に宣言する必要があります。

このルールは、実際にグローバル名前空間で名前を検索するように指示していませんが、リスト内の関数の外側の名前空間 (この場合はグローバル名前空間) について言及しており、段落 1 ではリストされた名前空間を検索するように指示されています。したがって、名前のルックアップを作成するにはこれで十分です。

驚くべきことに、内部の囲まれた名前空間を優先する再帰検索について言及していませんが、実際にはあなたの例にはそのようなものがないので、ここでやめます:) . コンパイルをコンパイラに任せ、問題が発生した場合にのみ手動で作業する方がはるかに高速です。

于 2013-07-02T23:49:19.123 に答える
1

あなたが与えた例ではX、修飾されていない名前の検索と見なされます。そのため、3.4.1 の規則に従います。

この場合、検索される名前空間は次のとおりです。

  1. main()定義前の関数のローカル名前空間。(7.3.1.4 では名前空間が定義されていない可能性があります。)
  2. グローバル名前空間。

残念ながら、名前空間名が他の名前と同じであると具体的に述べている標準の場所を指摘することはできません。しかし、彼らはそうです。名前検索は、実際にその名前の名前空間を見つけるまで、それが名前空間名 (クラス名または構造体名の可能性があります) であることを認識しません。

于 2013-07-02T23:26:07.593 に答える