Уточнение имени - PullRequest
       21

Уточнение имени

2 голосов
/ 04 ноября 2010

$ 10,2 / 4- "[Примечание: поиск имени в подробный спецификатор типа (3.4.4) или базовый спецификатор (раздел 10), для экземпляр, игнорирует все нетипичные декларации при поиске имени в спецификаторе вложенного имени (3.4.3) игнорирует функцию, переменную и объявления перечислителя. "

Я нашел это утверждение очень запутанным в этом разделе при описании поиска имени.

void S(){}

struct S{
   S(){cout << 1;}
   void f(){}
   static const int x = 0;
}; 

int main(){ 
   struct S *p = new struct ::S;  // here ::S refers to type
   p->::S::f();

   S::x;  // base specifier, ignores the function declaration 'S'

   ::S(); // nested name specifier, ignores the struct declaration 'S'.
   delete p;
} 

Мои вопросы:

  1. Правильно ли мое понимание правил?

  2. Почему ::S в строке, выполняющей new, автоматически трактуется как struct S, тогда как в последней строке ::S означает функции S в глобальном пространстве имен.

  3. Указывает ли это на двусмысленность в документации, или это еще один день для меня, чтобы держаться подальше от C ++ Standard?

Ответы [ 2 ]

1 голос
/ 04 ноября 2010

Q1: мне так кажется.

Q2: совместимость с C. Когда вы объявляете struct в C, имя тега - это просто имя тега.Чтобы использовать его в автономном режиме, вам нужно typedef.В C ++ вам не нужен typedef, который облегчает жизнь.Но правила C ++ были усложнены необходимостью импортировать уже существующие заголовки C, которые «перегружали» имя тега именем функции.Каноническим примером этого является функция Unix stat(), которая использует struct stat* в качестве аргумента.

Q3: Стандартное чтение обычно довольно сложно ... вам уже нужно знать, что в другом месте нет места для изменениячто ты читаешь.Не странно, что люди, знающие, как это сделать, являются языковыми юристами ...

0 голосов
/ 15 августа 2011

Вы ошибаетесь по поводу второго комментария.В S::x S - это имя в спецификаторе вложенного имени.Стандарт ссылается на «спецификатор базы»:

namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier

Вы также не правы по этому поводу:

::S(); // вложенное имяспецификатор, игнорирует объявление структуры 'S'.

Этот код вызывает функцию не потому, что ::S будет спецификатором вложенного имени (это не вложенное имя-specifier!), но поскольку имена функций скрывают имена классов или перечислений, если и функция, и класс / перечисление объявлены в одной и той же области видимости.

FWIW, следующий код будет одинаково действительным для строки 2main

p->S::f();

Важно то, что S предшествует ::, что заставляет поиск игнорировать функцию.То, что вы поставили :: перед S, не имеет никакого эффекта в вашем случае.

...