6 Basic concepts [basic]

6.4 Name lookup [basic.lookup]

6.4.1 Unqualified name lookup [basic.lookup.unqual]

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

Объявления из пространства имен, обозначенного символом a, using-directiveстановятся видимыми в пространстве имен, содержащем using-directive; см[namespace.udir]. Для целей правил поиска неквалифицированных имен, описанных в[basic.lookup.unqual], объявления из пространства имен, назначенного using-directiveэлементом, считаются членами этого включающего пространства имен.

Поиск неполного имени, используемого в postfix-expressionкачестве вызова функции, описан в[basic.lookup.argdep]. [ Note: Для определения (во время синтаксического анализа), является ли выражение postfix-expressionдля вызова функции, применяются обычные правила поиска имени. Правила[basic.lookup.argdep] не влияют на синтаксическую интерпретацию выражения. Например,

typedef int f;
namespace N {
  struct A {
    friend void f(A &);
    operator int();
    void g(A a) {
      int i = f(a);  // f is the typedef, not the friend function: equivalent to int(a)
    }
  };
}

Поскольку выражение не является вызовом функции,argument-dependent name lookup не применяется и функция другаf не найдена. ]end note

Имя, используемое в глобальной области видимости, вне какой-либо функции, класса или объявленного пользователем пространства имен, должно быть объявлено до его использования в глобальной области.

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

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

namespace A {
  namespace N {
    void f();
  }
}
void A::N::f() {
  i = 5;
  // The following scopes are searched for a declaration of i:
  // 1) outermost block scope of A​::​N​::​f, before the use of i
  // 2) scope of namespace N
  // 3) scope of namespace A
  // 4) global scope, before the definition of A​::​N​::​f
}

end example]

Имя , используемое в определении классаX внешней функции члена тела, аргумент по умолчанию, noexcept-specifier, brace-or-equal-initializerиз нестатического элемента данных или определения вложенного класса ,30 должны быть объявлен в одном из следующих способов:

  • перед его использованием в классеX или быть членом базового классаX ([class.member.lookup]), или

  • ifX является anested class of class Y, до определенияX in Y, или должен быть членом базового классаY (этот поиск применяется, в свою очередь, кYохватывающим классам, начиная с самого внутреннего включающего класса),31 или

  • еслиX являетсяlocal class или является вложенным классом локального класса, перед определением классаX в блоке, включающем определение классаX, или

  • ifX является членом пространства именN, или является вложенным классом класса, который является членомN, или является локальным классом, или вложенным классом в локальном классе функции, которая является членом N, до определения классаX в пространстве имен N или в одном изNзакрывающих пространств имен.

[Example:

namespace M {
  class B { };
}
namespace N {
  class Y : public M::B {
    class X {
      int a[i];
    };
  };
}

// The following scopes are searched for a declaration of i:
// 1) scope of class N​::​Y​::​X, before the use of i
// 2) scope of class N​::​Y, before the definition of N​::​Y​::​X
// 3) scope of N​::​Y's base class M​::​B
// 4) scope of namespace N, before the definition of N​::​Y
// 5) global scope, before the definition of N

end example] [ Note: При поиске предыдущего объявления класса или функции, введенногоfriend объявлением, области за пределами самой внутренней области охватывающего пространства имен не рассматриваются; см[namespace.memdef]. ] [ далее описывает ограничения на использование имен в определении класса. далее описывает ограничения на использование имен в определениях вложенных классов. далее описывает ограничения на использование имен в определениях локальных классов. ]end noteNote:[basic.scope.class][class.nest] [class.local] end note

Для членов класса должно быть объявленоXимя, используемое в теле функции-члена, в аргументе по умолчанию, в a noexcept-specifier, в brace-or-equal-initializeranon-static data memberили в определении члена класса вне определенияX, следующее за членом. declarator-id32одним из следующих способов:

  • перед его использованием в блоке, в котором он используется, или во включающем блоке ([stmt.block]), или

  • должен быть членом классаX или быть членом базового классаX ([class.member.lookup]), или

  • ifX являетсяnested class классомY, должен быть членомYили должен быть членом базового классаY (этот поиск применяется, в свою очередь, кYвключающим классам, начиная с самого внутреннего включающего класса),33 или

  • еслиX являетсяlocal class или является вложенным классом локального класса, перед определением классаX в блоке, включающем определение классаX, или

  • ifX является членом пространства именNили является вложенным классом класса, который является членомN, или является локальным классом или вложенным классом в локальном классе функции, которая является членом N, до использования имени, в пространстве именN или в одном изNвключающих пространств имен.

[Example:

class B { };
namespace M {
  namespace N {
    class X : public B {
      void f();
    };
  }
}
void M::N::X::f() {
  i = 16;
}

// The following scopes are searched for a declaration of i:
// 1) outermost block scope of M​::​N​::​X​::​f, before the use of i
// 2) scope of class M​::​N​::​X
// 3) scope of M​::​N​::​X's base class B
// 4) scope of namespace M​::​N
// 5) scope of namespace M
// 6) global scope, before the definition of M​::​N​::​X​::​f

end example] [ Note:[class.mfct] и[class.static] далее опишите ограничения на использование имен в определениях функций-членов.[class.nest] далее описывает ограничения на использование имен в рамках вложенных классов.[class.local] далее описывает ограничения на использование имен в определениях локальных классов. ]end note

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

Вfriend объявлении, называющем функцию-член, имя, используемое в деклараторе функции, а не часть a template-argument в, declarator-idсначала ищется в области действия class ([class.member.lookup]) функции-члена . Если он не найден или если имя является частью a template-argumentв declarator-id, поиск выполняется так, как описано для неквалифицированных имен в определении класса, предоставляющего дружбу. [Example:

struct A {
  typedef int AT;
  void f1(AT);
  void f2(float);
  template <class T> void f3();
};
struct B {
  typedef char AT;
  typedef float BT;
  friend void A::f1(AT);      // parameter type is A​::​AT
  friend void A::f2(BT);      // parameter type is B​::​BT
  friend void A::f3<AT>();    // template argument is B​::​AT
};

end example]

Во время поиска имени, используемого в качествеdefault argument в функции parameter-declaration-clauseили используемого в expressionэлементе mem-initializerдля конструктора ([class.base.init]), имена параметров функции видны и скрывают имена сущностей, объявленных в областях блока, класса или пространства имен, содержащих объявление функции. [ Note: [dcl.fct.default] далее описывает ограничения на использование имен в аргументах по умолчанию.[class.base.init] далее описывает ограничения на использование имен в ctor-initializer. ]end note

Во время поиска имени, используемого в constant-expressionобъекте enumerator-definition, ранее объявленные enumerators в перечислении становятся видимыми и скрывают имена сущностей, объявленных в областях блока, класса или пространства имен, содержащих enum-specifier.

Имя, используемое в определенииstatic data member классаX (после qualified-id статического члена) ищется, как если бы имя использовалось в функции-члене классаX. [ Note:[class.static.data] далее описывает ограничения на использование имен в определении элемента static данных. ]end note

Если переменный член пространства имен определен вне области его пространства имен, то любое имя, которое появляется в определении члена (после declarator-id), ищется так, как если бы определение члена произошло в его пространстве имен. [Example:

namespace N {
  int i = 4;
  extern int j;
}

int i = 2;

int N::j = i;       // N​::​j == 4

end example]

Имя, используемое в обработчике для a function-try-block, ищется так, как если бы имя использовалось во внешнем блоке определения функции. В частности, имена параметров функции не должны повторно объявляться exception-declarationни в самом внешнем блоке обработчика, ни в самом внешнем блоке обработчика function-try-block. Имена, объявленные во внешнем блоке определения функции, не обнаруживаются при поиске в области обработчика для function-try-block. [ Note: Но имена параметров функции найдены. ]end note

[ Note: Правила поиска имени в определениях шаблонов описаны в[temp.res]. ]end note

Это относится к неквалифицированным именам, которые встречаются, например, в типе или аргументе по умолчанию в parameter-declaration-clauseили используются в теле функции.

Это относится к неквалифицированным именам, следующим за именем класса; такое имя может использоваться в base-clauseили может использоваться в определении класса.

Этот поиск применяется независимо от того, вложено ли определениеX вYопределение илиXпоявляется ли определение в области пространства имен, включающейYопределение ([class.nest]).

То есть неквалифицированное имя, которое встречается, например, в типе в parameter-declaration-clauseили в noexcept-specifier.

Этот поиск применяется независимо от того, определенаX ли функция-член в определении класса или функция-член определена в области пространства имен, содержащейXопределение.