Где определено правило поиска имени, которое находит самое непосредственное объявление имени?

int i;
void f()
{
    int i{};
    {
        int a = i; // local or global 'i'?
    }
}

Мой вопрос не в том, какой i выбирается, поскольку ясно, что это локальный, а в том, где в стандарте указано.

Самое близкое правило, которое я смог найти, это [basic.lookup.unqual]p6, в котором говорится:

В определении функции, которая является членом пространства имен N, имя, используемое после declarator-id функции, должно быть объявлено до его использования в блоке, в котором оно используется, или в одном из его охватывающих блоков. блоков ([stmt.block]) или должен быть объявлен до его использования в пространстве имен N, или, если N является вложенным пространством имен, должен быть объявлен до его использования в одном из включающих N пространств имен.

Но там просто сказано, что имя должно быть объявлено за некоторое время до использования; это не то, что я ищу. Пример в том же абзаце делает все более ясным, поскольку говорит, какие области поиска и в каком порядке, но это пример и, как таковой, не именительный падеж.

Все остальные абзацы в [basic.lookup.unqual] не применяются к функциям, не являющимся членами. Итак, мой вопрос: где в стандарте это указано?


person Rakete1111    schedule 28.07.2018    source источник
comment
@melpomene Это просто описывает область действия объекта, а не то, как работает поиск имени IIUC.   -  person Rakete1111    schedule 28.07.2018
comment
Да, но поиск имени ищет в областях, и в вашем примере глобальный i не входит в область действия (согласно моей другой ссылке).   -  person melpomene    schedule 28.07.2018
comment
@melpomene Ооооо, я понял. Я неправильно прочитал эту часть. Теперь это имеет смысл... :) (возможно, вы захотите написать ответ, кстати)   -  person Rakete1111    schedule 28.07.2018


Ответы (1)


В [basic.scope.declarative] мы имеем:

  1. Каждое имя вводится в некоторую часть текста программы, называемую декларативной областью, которая является самой большой частью программы, в которой это имя допустимо, то есть в которой это имя может использоваться как неполное имя для ссылки на один и тот же объект. Как правило, каждое конкретное имя допустимо только в некоторой, возможно, несмежной части текста программы, называемой его областью действия. Чтобы определить область действия объявления, иногда удобно обратиться к потенциальной области действия объявления. Область действия объявления такая же, как и ее потенциальная область, если только потенциальная область не содержит другое объявление с тем же именем. В этом случае потенциальная область объявления во внутренней (содержащей) декларативной области исключается из области действия объявления во внешней (содержащей) декларативной области.

  2. [ Пример: В

    int j = 24;
    int main() {
      int i = j, j;
      j = 42;
    }
    

    идентификатор j объявляется дважды как имя (и используется дважды). Декларативная область первого j включает весь пример. Потенциальная область действия первого j начинается сразу после j и простирается до конца программы, но ее (фактическая) область действия исключает текст между , и }. Декларативная область второго объявления j (j непосредственно перед точкой с запятой) включает весь текст между { и }, но ее потенциальная область действия исключает объявление i. Область действия второго объявления j такая же, как и ее потенциальная область действия. — конец примера ]

(Выделение мое.)

В твоей

int a = i;

Например, i должен ссылаться на локальный i, потому что глобальный i здесь буквально не рассматривается.

Как сказано в начале [basic.lookup.unqual]:

Во всех случаях, перечисленных в [basic.lookup.unqual], области видимости ищут объявление в порядке, указанном в каждой из соответствующих категорий [...]

Но не имеет значения, какой порядок поиска мы выбираем, если изначально в области видимости находится только одно объявление.

person melpomene    schedule 28.07.2018