Я не понимаю 3.4 / 2 в стандарте

Я не понимаю 3.4 / 2 в Стандарте:

Имя «посмотрел вверх в контексте выражения» выглядит как
неполное имя в области, в которой найдено выражение.

Что делать, если имя квалифицировано, как N::i ниже?

#include <iostream>

namespace N { int i = 1; }

int main()
{
int i = 0;

std::cout << N::i << '\n';
}

Квалифицированное имя N::i не ищется в области, где N::i найден, то есть он не был найден в области видимости main () и глобальной области видимости!

4

Решение

Чтобы расширить комментарий @JerryCoffin, правила для квалифицированного поиска:

3.4.3 Поиск по квалифицированному имени [basic.lookup.qual]

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

Вот пример:

#include <iostream>

struct N { enum { i = 1 }; };

int main()
{
std::cout << N::i << '\n'; // prints 1

struct N { enum { i = 0 }; };

std::cout << N::i << '\n'; // prints 0
}

Живой пример.

0

Другие решения

Сначала левая сторона :: смотрит вверх, а затем правая сторона смотрит вверх внутри него. Итак, чтобы посмотреть N::iсначала находит N используя неквалифицированный поиск, то он заглядывает внутрь N найти i, Просто!

В вашем примере вы переопределяете N на местном уровне. После локального определения внешнее определение скрыто согласно §3.3.10: «Имя может быть скрыто явным объявлением того же имени во вложенной декларативной области или производном классе».

Поскольку компилятор с самого начала знает, что левая часть (N) должен выдавать тип, пространство имен или перечисление, любые другие результаты поиска (то есть функции, переменные и шаблоны) игнорируются. Итак, вы также можете сделать:

#include <iostream>

struct N { enum { i = 1 }; };

int main()
{
int N = 3;
std::cout << N::i << '\n'; // prints 1
std::cout << N << '\n'; // prints 3

struct N { enum { i = 0 }; };

std::cout << N::i << '\n'; // prints 0
}

http://coliru.stacked-crooked.com/a/9a7c9e34b1e74ce7

См. §3.4.3 / 1:

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

0

По вопросам рекламы [email protected]