Точка из проекта ISO C ++ (n3290): 3.4.3.2/1 Члены пространства имен - PullRequest
4 голосов
/ 10 августа 2011

Точка из черновика ISO C ++ (n3290): 3.4.3.2/1 Члены пространства имен

Если спецификатор вложенного имени квалифицированного идентификатора назначает пространство имен, имя, указанное после поиска спецификатора вложенного имени в область пространства имен. Если квалифицированный идентификатор начинается с ::, имя после :: ищется в глобальном пространстве имен. В любом случай, имена в шаблоне-аргументе шаблона-ID ищутся в контексте, в котором происходит все постфиксное выражение.

Здесь можно рассказать о BOLD-части .... и с более ранних черновиков с ++ 03 до чернового с ++ 0x он добавил

Если квалифицированный идентификатор начинается с ::, ищется имя после :: в глобальном пространстве имен.

Может ли кто-нибудь объяснить с помощью примера программы, пожалуйста

Ответы [ 4 ]

5 голосов
/ 10 августа 2011

Он называется Поиск квалифицированного имени .
Ведущий :: относится к глобальному пространству имен.Любой квалифицированный идентификатор, начинающийся с ::, всегда будет ссылаться на некоторый идентификатор в глобальном пространстве имен поверх того же именованного идентификатора в местном пространстве имен.

5 голосов
/ 10 августа 2011

::S является квалифицированным идентификатором.

В квалифицированном идентификаторе ::S::f, S:: является спецификатором вложенного имени.

В неформальных терминах вложенныйспецификатор-имени - это часть идентификатора, которую

  • начинается либо в самом начале квалифицированного идентификатора, либо после оператора разрешения исходной области (: :), если он появляется в самом началеИдентификатор и
  • заканчиваются последним оператором разрешения области в квалифицированном идентификаторе.

Очень неофициально, идентификатор является либо квалифицированным идентификатором, либо неквалифицированным идентификатором.Если идентификатор является квалифицированным идентификатором, он фактически состоит из двух частей: спецификатора вложенного имени, за которым следует неквалифицированный идентификатор.

Дано:

struct  A {
    struct B {
        void F();
    };
};
  • A - это неквалифицированный идентификатор.
  • ::A - квалифицированный идентификатор, но не имеет спецификатора вложенного имени.
  • A::B - квалифицированный идентификатор, а A:: -спецификатор вложенного имени.
  • ::A::B является квалифицированным идентификатором, а A:: является спецификатором вложенного имени.
  • A::B::F является квалифицированным идентификатором, и оба B:: и A::B:: являются спецификаторами вложенных имен.
  • ::A::B::F является квалифицированными идентификаторами, а B:: и A::B:: являются спецификаторами вложенных имен.

Другой пример:

#include <iostream>
using namespace std;

int count(0);                   // Used for iteration

class outer {
public:
    static int count;           // counts the number of outer classes
    class inner {
    public:
        static int count;       // counts the number of inner classes
    };
};

int outer::count(42);            // assume there are 42 outer classes
int outer::inner::count(32768);  // assume there are 2^15 inner classes
                                 // getting the hang of it?

int main() {
    // how do we access these numbers?
    //
    // using "count = ?" is quite ambiguous since we don't explicitly know which
    // count we are referring to.
    //
    // Nested name specifiers help us out here

    cout << ::count << endl;        // The iterator value
    cout << outer::count << endl;           // the number of outer classes instantiated
    cout << outer::inner::count << endl;    // the number of inner classes instantiated
    return 0;
}

РЕДАКТИРОВАТЬ:

В ответ на ваш комментарий, я считаю, что утверждение просто означает, что аргументы шаблона обрабатываются в контексте и строке, с помощью которых ониобъявлены.Например,

в f.~foo();, foo ищется в пределах f., а в пределах foo<int> допустимо ссылаться на него только с помощью foo.

2 голосов
/ 10 августа 2011

Текст, выделенный жирным шрифтом, относится к двум различным ситуациям.Первая часть - это различие использования или не использования :: в качестве префикса.Когда определенное имя начинается с ::, проверяется точное пространство имен, начиная с пустого пространства имен, а если оно отсутствует, поиск будет учитывать вложенные пространства имен:

namespace A {
    void f() { std::cout << "::A::f" << std::endl; }
}
namespace B {
    namespace A {
        void f() { std::cout << "::B::A::f" << std::endl; }
    }
    void g() {
        A::f();     // ::B::A::f
        ::A::f();   // ::A::f
    }
}

Последнее предложение в абзаце относитсяк конкретным аргументам шаблона, и он говорит вам, что поиск не начнется в пространстве имен, в котором был объявлен шаблон, а скорее в пространстве имен, в котором он создается:

struct A {
    static void f() { std::cout << "::A::f()" << std::endl; }
};
template <typename T>
void f() {
    T::f();
}
namespace N {
    struct A {
        static void f() { std::cout << "::N::A::f()" << std::endl; }
    };
    void g() {
        f<A>();
    }
}

Если поиск начался впространство имен шаблона, вызов f<A>() будет ссылаться на f<::A>, но в этом условии в стандарте говорится, что поиск начнется внутри пространства имен N (, где происходит полное постфиксное выражение ), и будеттаким образом назовите ::N::A::f().

0 голосов
/ 11 августа 2011
int a(1);

class someCls {
  private:
    int a;
  public:
    // Assigns this->a with the value of the global variable ::a.
    void assignFromGlobal() {
      a = ::a;
    }
};
...