10 Declarations [dcl.dcl]

10.3 Namespaces [basic.namespace]

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

Самая внешняя декларативная область единицы перевода - это пространство имен; см [basic.scope.namespace].

10.3.1 Namespace definition [namespace.def]

namespace-name:
	identifier
	namespace-alias
namespace-definition:
	named-namespace-definition
	unnamed-namespace-definition
	nested-namespace-definition
named-namespace-definition:
	inlineopt namespace attribute-specifier-seqopt identifier { namespace-body }
unnamed-namespace-definition:
	inlineopt namespace attribute-specifier-seqopt { namespace-body }
nested-namespace-definition:
	namespace enclosing-namespace-specifier :: identifier { namespace-body }
enclosing-namespace-specifier:
	identifier
	enclosing-namespace-specifier :: identifier
namespace-body:
	declaration-seqopt

Каждый namespace-definitionдолжен появиться в глобальной области видимости или в области видимости пространства имен ([basic.scope.namespace]).

В named-namespace-definition, то identifierэто имя пространства имен. Если identifierпри поиске ([basic.lookup.unqual]) относится к namespace-name(но не a namespace-alias), которое было введено в пространство имен, в котором named-namespace-definitionпоявляется, или которое было введено в члене встроенного набора пространств имен этого пространства имен, namespace-definition extends ранее объявленное пространство имен. В противном случае identifierвводится как namespace-nameв декларативную область, в которой named-namespace-definitionпоявляется.

Поскольку a namespace-definitionсодержится declarations в его, namespace-bodyа a namespace-definitionсамо является a declaration, отсюда следует, что он namespace-definitions может быть вложенным. [Example:

namespace Outer {
  int i;
  namespace Inner {
    void f() { i++; }           // Outer​::​i
    int i;
    void g() { i++; }           // Inner​::​i
  }
}

end example]

Объектами enclosing namespaces объявления являются те пространства имен, в которых объявление появляется лексически, за исключением повторного объявления члена пространства имен вне его исходного пространства имен (например, определения, как указано в [namespace.memdef]). Такое повторное объявление имеет те же охватывающие пространства имен, что и исходное объявление. [Example:

namespace Q {
  namespace V {
    void f();                   // enclosing namespaces are the global namespace, Q, and Q​::​V
    class C { void m(); };
  }
  void V::f() {                 // enclosing namespaces are the global namespace, Q, and Q​::​V
    extern void h();            // ... so this declares Q​::​V​::​h
  }
  void V::C::m() {              // enclosing namespaces are the global namespace, Q, and Q​::​V
  }
}

end example]

Если необязательное начальное inline ключевое слово появляется в a namespace-definitionдля определенного пространства имен, это пространство имен объявляется inline namespace. inline Ключевое слово может быть использовано на namespace-definitionкоторый расширяет пространство имен , только если он был ранее использован на namespace-definition том , что изначально объявлено namespace-nameдля этого пространства имен.

Необязательный параметр attribute-specifier-seq в a named-namespace-definition принадлежит определяемому или расширяемому пространству имен.

Члены встроенного пространства имен можно использовать во многих отношениях, как если бы они были членами включающего пространства имен. В частности, встроенное пространство имен и его включающее пространство имен добавляются к набору связанных пространств имен, используемых argument-dependent lookup всякий раз, когда одно из них есть, а элемент, using-directiveкоторый именует встроенное пространство имен, неявно вставляется во включающее пространство имен, как для unnamed namespace. Кроме того, каждый член инлайн пространства имен может впоследствии быть partially specialized, explicitly instantiatedили , explicitly specialized как если бы она была членом пространства имен вмещающих. Наконец, поиск имени в охватывающем пространстве имен с помощью явной qualification ([namespace.qual]) будет включать элементы встроенного пространства имен, внесенных с помощью, using-directiveдаже если есть объявления этого имени во включающем пространстве имен.

Эти свойства являются транзитивными: если пространство имен N содержит встроенное пространство имен M, которое, в свою очередь, содержит встроенное пространство имен O, тогда члены O могут использоваться, как если бы они были членами M или N. inline namespace set Из N является транзитивным замыканием всех встроенных пространств имен в N. enclosing namespace set Из O есть множество пространств имен , состоящие из самих внутренних без встроенного пространства имен , охватывающего инлайн пространства имен O, вместе с любыми промежуточным инлайн пространствами имен.

A nested-namespace-definitionс символом enclosing-namespace-specifier E, identifier I и namespace-body B эквивалентно

namespace E { namespace I { B } }

[Example:

namespace A::B::C {
  int i;
}

Вышеупомянутое имеет тот же эффект, что и:

namespace A {
  namespace B {
    namespace C {
      int i;
    }
  }
}

end example]

10.3.1.1 Unnamed namespaces [namespace.unnamed]

Ведет unnamed-namespace-definitionсебя так, как если бы его заменили на

inlineopt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

где inline появляется тогда и только тогда, когда он появляется в unnamed-namespace-definition и все вхождения unique в единицу перевода заменяются одним и тем же идентификатором, и этот идентификатор отличается от всех других идентификаторов в единице перевода. Опциональная attribute-specifier-seq в unnamed-namespace-definition appertains к unique. [Example:

namespace { int i; }            // unique​::​i
void f() { i++; }               // unique​::​i++

namespace A {
  namespace {
    int i;                      // A​::​unique​::​i
    int j;                      // A​::​unique​::​j
  }
  void g() { i++; }             // A​::​unique​::​i++
}

using namespace A;
void h() {
  i++;                          // error: unique​::​i or A​::​unique​::​i
  A::i++;                       // A​::​unique​::​i
  j++;                          // A​::​unique​::​j
}

end example]

10.3.1.2 Namespace member definitions [namespace.memdef]

Объявление в пространстве имен N (за исключением объявлений во вложенных областях), declarator-idкоторое является unqualified-id([dcl.meaning]), class-head-nameили enum-head-nameявляется identifier, или elaborated-type-specifierимеет форму ( ), или это , объявляет (или повторно объявляет) его или в качестве члена . [ Или шаблон не ввести имя и , таким образом , может быть объявлено используя в качестве члена множества вшито пространства имен, если основной шаблон объявлен в инлайн пространстве имен. ] [class-key attribute-specifier-seqopt identifier[dcl.type.elab]opaque-enum-declarationunqualified-ididentifier NNote: explicit instantiation explicit specialization unqualified-idend noteExample:

namespace X {
  void f() { /* ... */ }        // OK: introduces X​::​f()

  namespace M {
    void g();                   // OK: introduces X​::​M​::​g()
  }
  using M::g;
  void g();                     // error: conflicts with X​::​M​::​g()
}

end example]

Члены именованного пространства имен также могут быть определены вне этого пространства имен с помощью явной qualification ([namespace.qual]) определяемого имени при условии, что определяемая сущность уже была объявлена ​​в пространстве имен и определение появляется после точки объявления в пространстве имен, которое включает пространство имен декларации. [Example:

namespace Q {
  namespace V {
    void f();
  }
  void V::f() { /* ... */ }     // OK
  void V::g() { /* ... */ }     // error: g() is not yet a member of V
  namespace V {
    void g();
  }
}

namespace R {
  void Q::V::g() { /* ... */ }  // error: R doesn't enclose Q
}

end example]

Если friend объявление в нелокальном классе сначала объявляет класс, функцию, шаблон класса или шаблон функции,97 то друг является членом самого внутреннего включающего пространства имен. friend Декларация сама по себе не делает имя видимым для неквалифицированного поиска ([basic.lookup.unqual]) или квалифицированного поиска ([basic.lookup.qual]). [ Note: Имя друга будет видно в его пространстве имен, если соответствующее объявление предоставлено в области пространства имен (либо до, либо после определения класса, предоставляющего дружбу). ] Если вызывается дружественная функция или шаблон функции, ее имя можно найти с помощью поиска по именам, который рассматривает функции из пространств имен и классов, связанных с типами аргументов функции ( ). Если имя в объявлении не является ни квалифицированным, ни a, а объявление является функцией или объектом, поиск для определения того, была ли объект объявлен ранее, не должен учитывать какие-либо области за пределами самого внутреннего включающего пространства имен. [ Другие формы объявлений не могут объявлять новый член самого внутреннего включающего пространства имен и, таким образом, следовать обычным правилам поиска. ] [end note[basic.lookup.argdep] friend template-idelaborated-type-specifierNote: friend end noteExample:

// Assume f and g have not yet been declared.
void h(int);
template <class T> void f2(T);
namespace A {
  class X {
    friend void f(X);           // A​::​f(X) is a friend
    class Y {
      friend void g();          // A​::​g is a friend
      friend void h(int);       // A​::​h is a friend
                                // ​::​h not considered
      friend void f2<>(int);    // ​::​f2<>(int) is a friend
    };
  };

  // A​::​f, A​::​g and A​::​h are not visible here
  X x;
  void g() { f(x); }            // definition of A​::​g
  void f(X) { /* ... */ }       // definition of A​::​f
  void h(int) { /* ... */ }     // definition of A​::​h
  // A​::​f, A​::​g and A​::​h are visible here and known to be friends
}

using A::x;

void h() {
  A::f(x);
  A::X::f(x);                   // error: f is not a member of A​::​X
  A::X::Y::g();                 // error: g is not a member of A​::​X​::​Y
}

end example]

это означает, что имя класса или функции неквалифицировано.

10.3.2 Namespace alias [namespace.alias]

A namespace-alias-definitionобъявляет альтернативное имя для пространства имен в соответствии со следующей грамматикой:

namespace-alias:
	identifier
namespace-alias-definition:
	namespace identifier = qualified-namespace-specifier ;
qualified-namespace-specifier:
	nested-name-specifieropt namespace-name

Символ identifierв a namespace-alias-definitionявляется синонимом имени пространства имен, обозначаемого символом qualified-namespace-specifierи становится a namespace-alias. [ Note: При поиске a namespace-nameв a namespace-alias-definitionучитываются только имена пространств имен, см [basic.lookup.udir]. ]end note

В декларативной области a namespace-alias-definitionможно использовать для переопределения, namespace-aliasобъявленного в этой декларативной области, чтобы ссылаться только на пространство имен, на которое оно уже ссылается. [ Example: Следующие декларации составлены правильно:

namespace Company_with_very_long_name { /* ... */ }
namespace CWVLN = Company_with_very_long_name;
namespace CWVLN = Company_with_very_long_name;  // OK: duplicate
namespace CWVLN = CWVLN;

end example]

10.3.3 The using declaration [namespace.udecl]

using-declaration:
	using using-declarator-list ;
using-declarator-list:
	using-declarator ...opt
	using-declarator-list , using-declarator ...opt
using-declarator:
	typenameopt nested-name-specifier unqualified-id

Каждый using-declaratorв a using-declaration98 вводит набор объявлений в декларативную область, в которой using-declarationпоявляется. Набор объявлений, представленных объектом, using-declaratorнаходится путем выполнения поиска по квалифицированному имени ([basic.lookup.qual], [class.member.lookup]) для имени в using-declarator, за исключением функций, которые скрыты, как описано ниже. Если using-declaratorне называет конструктор, unqualified-idобъявляется в декларативной области, в которой using-declarationпоявляется как синоним для каждого объявления, представленного using-declarator. [ Note: Так объявляется только указанное имя; указание имени перечисления в a using-declaration не объявляет его перечислители в using-declarationдекларативной области. ] Если именует конструктор, он объявляет, что класс - это набор объявлений конструктора, представленных от назначенного базового класса.end noteusing-declarator inherits using-declarator

Every using-declaration- это a declarationи a, member-declarationпоэтому их можно использовать в определении класса. [Example:

struct B {
  void f(char);
  void g(char);
  enum E { e };
  union { int x; };
};

struct D : B {
  using B::f;
  void f(int) { f('c'); }       // calls B​::​f(char)
  void g(int) { g('c'); }       // recursively calls D​::​g(int)
};

end example]

В using-declarationиспользуются в качестве member-declaration, каждый using-declarator«s nested-name-specifier будет называть базовый класс определяемым класса. Если a using-declaratorназывает конструктор, он nested-name-specifierдолжен называть прямой базовый класс определяемого класса. [Example:

template <typename... bases>
struct X : bases... {
  using bases::g...;
};

X<B, D> x;                      // OK: B​::​g and D​::​g introduced

end example] [Example:

class C {
  int g();
};

class D2 : public B {
  using B::f;                   // OK: B is a base of D2
  using B::e;                   // OK: e is an enumerator of base B
  using B::x;                   // OK: x is a union member of base B
  using C::g;                   // error: C isn't a base of D2
};

end example]

[ Note: Поскольку деструкторы не имеют имен, a using-declarationне может ссылаться на деструктор базового класса. Поскольку специализации шаблонов членов для функций преобразования не могут быть найдены с помощью поиска по имени, они не учитываются, когда a using-declarationуказывает функцию преобразования ([temp.mem]). ] Если конструктор или оператор присваивания, перенесенный из базового класса в производный класс, имеет сигнатуру конструктора копирования / перемещения или оператора присваивания для производного класса ( ), сам по себе не подавляет неявное объявление члена производного класса; член базового класса скрыт или переопределен неявно объявленным конструктором копирования / перемещения или оператором присваивания производного класса, как описано ниже.end note[class.copy]using-declaration

A using-declarationне должен называть a template-id. [Example:

struct A {
  template <class T> void f(T);
  template <class T> struct X { };
};
struct B : A {
  using A::f<double>;           // ill-formed
  using A::X<int>;              // ill-formed
};

end example]

A using-declarationне должен называть пространство имен.

A using-declarationне должен называть перечислителя с ограниченной областью видимости.

Имя using-declarationчлена класса должно быть member-declaration. [Example:

struct X {
  int i;
  static int s;
};

void f() {
  using X::i;                   // error: X​::​i is a class member and this is not a member declaration.
  using X::s;                   // error: X​::​s is a class member and this is not a member declaration.
}

end example]

На члены, объявленные a, using-declarationможно ссылаться с помощью явной квалификации, как и на другие имена членов ([namespace.qual]). [Example:

void f();

namespace A {
  void g();
}

namespace X {
  using ::f;                    // global f
  using A::g;                   // A's g
}

void h()
{
  X::f();                       // calls ​::​f
  X::g();                       // calls A​::​g
}

end example]

A using-declaration- это a declarationи поэтому может использоваться повторно там, где (и только когда) разрешено несколько объявлений. [Example:

namespace A {
  int i;
}

namespace A1 {
  using A::i, A::i;             // OK: double declaration
}

struct B {
  int i;
};

struct X : B {
  using B::i, B::i;             // error: double member declaration
};

end example]

[ Note: Для элемента, using-declaration чьи nested-name-specifierимена являются пространством имен, члены, добавленные к пространству имен после элемента using-declaration , не входят в набор представленных объявлений, поэтому они не учитываются при использовании имени. Таким образом, дополнительные перегрузки, добавленные после using-declaration, игнорируются, но учитываются аргументы функции по умолчанию ([dcl.fct.default]), аргументы шаблона по умолчанию ([temp.param]) и специализации шаблона ([temp.class.spec], [temp.expl.spec]). ] [ end noteExample:

namespace A {
  void f(int);
}

using A::f;         // f is a synonym for A​::​f; that is, for A​::​f(int).
namespace A {
  void f(char);
}

void foo() {
  f('a');           // calls f(int), even though f(char) exists.
}

void bar() {
  using A::f;       // f is a synonym for A​::​f; that is, for A​::​f(int) and A​::​f(char).
  f('a');           // calls f(char)
}

end example]

[ Note: Частичные специализации шаблонов классов можно найти путем поиска основного шаблона класса и последующего рассмотрения всех частичных специализаций этого шаблона. Если a using-declarationназывает шаблон класса, частичные специализации, введенные после using-declaration, фактически видны, потому что первичный шаблон является видимым ([temp.class.spec]). ]end note

Поскольку a using-declarationявляется объявлением, ограничения на одноименное объявление в нем declarative region также применяются к using-declarations. [Example:

namespace A {
  int x;
}

namespace B {
  int i;
  struct g { };
  struct x { };
  void f(int);
  void f(double);
  void g(char);     // OK: hides struct g
}

void func() {
  int i;
  using B::i;       // error: i declared twice
  void f(char);
  using B::f;       // OK: each f is a function
  f(3.5);           // calls B​::​f(double)
  using B::g;
  g('a');           // calls B​::​g(char)
  struct g g1;      // g1 has class type B​::​g
  using B::x;
  using A::x;       // OK: hides struct B​::​x
  x = 99;           // assigns to A​::​x
  struct x x1;      // x1 has class type B​::​x
}

end example]

Если объявление функции в области пространства имен или области блока имеет то же имя и то же самое, parameter-type-list что и функция, представленная с помощью a using-declaration, и объявления не объявляют ту же функцию, программа имеет неправильный формат. Если объявление шаблона функции в области пространства имен имеет то же имя, список типов параметров, возвращаемый тип и список параметров шаблона, что и шаблон функции, введенный с помощью a using-declaration, программа имеет неправильный формат. [ Note: Двое using-declarations могут вводить функции с одним и тем же именем и одним и тем же списком типов параметров. Если для вызова неквалифицированного имени функции разрешение перегрузки функции выбирает функции, введенные таким образом using-declarations, вызов функции имеет неправильный формат. [Example:

namespace B {
  void f(int);
  void f(double);
}
namespace C {
  void f(int);
  void f(double);
  void f(char);
}

void h() {
  using B::f;       // B​::​f(int) and B​::​f(double)
  using C::f;       // C​::​f(int), C​::​f(double), and C​::​f(char)
  f('h');           // calls C​::​f(char)
  f(1);             // error: ambiguous: B​::​f(int) or C​::​f(int)?
  void f(int);      // error: f(int) conflicts with C​::​f(int) and B​::​f(int)
}

end example] ]end note

Когда a using-declaratorпереносит объявления из базового класса в производный класс, функции-члены и шаблоны функций-членов в производном классе переопределяют и / или скрывают функции-члены и шаблоны функций-членов с тем же именем parameter-type-list,, cv-qualification и ref-qualifier(если есть) в базовый класс (а не конфликтующий). Такие скрытые или переопределенные объявления исключаются из набора объявлений, введенных платформой using-declarator. [Example:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      // OK: D​::​f(int) overrides B​::​f(int);

  using B::g;
  void g(char);     // OK

  using B::h;
  void h(int);      // OK: D​::​h(int) hides B​::​h(int)
};

void k(D* p)
{
  p->f(1);          // calls D​::​f(int)
  p->f('a');        // calls B​::​f(char)
  p->g(1);          // calls B​::​g(int)
  p->g('a');        // calls D​::​g(char)
}

struct B1 {
  B1(int);
};

struct B2 {
  B2(int);
};

struct D1 : B1, B2 {
  using B1::B1;
  using B2::B2;
};
D1 d1(0);           // ill-formed: ambiguous

struct D2 : B1, B2 {
  using B1::B1;
  using B2::B2;
  D2(int);          // OK: D2​::​D2(int) hides B1​::​B1(int) and B2​::​B2(int)
};
D2 d2(0);           // calls D2​::​D2(int)

end example]

В целях разрешения перегрузки функции, которые вводятся using-declarationв производный класс, обрабатываются так, как если бы они были членами производного класса. В частности, неявный this параметр следует рассматривать как указатель на производный класс, а не на базовый класс. Это не влияет на тип функции, и во всех других отношениях функция остается членом базового класса. Кроме того, конструкторы, которые вводятся через А using-declaration , рассматриваются как если бы они были конструкторами производного класса при поиске конструкторов производного класса ([class.qual]) или формирования набора кандидатов перегрузки ([over.match.ctor], [over.match.copy], [over.match.list]). Если такой конструктор выбран для выполнения инициализации объекта типа класса, все подобъекты, кроме базового класса, из которого произошел конструктор, инициализируются неявно ([class.inhctor.init]).

В a using-declarator, который не называет конструктор, все члены набора введенных объявлений должны быть доступны. В элементе, using-declaratorкоторый называет конструктор, проверка доступа не выполняется. В частности, если производный класс использует using-declaratorдля доступа к члену базового класса, имя члена должно быть доступно. Если имя совпадает с именем перегруженной функции-члена, тогда все указанные функции должны быть доступны. Члены базового класса, упомянутые a, using-declaratorдолжны быть видимы в области видимости по крайней мере одного из прямых базовых классов класса, в котором using-declaratorуказан.

[ Note: Поскольку a using-declaratorобозначает член базового класса (а не подобъект члена или функцию члена подобъекта базового класса), a using-declaratorнельзя использовать для разрешения унаследованных двусмысленностей членов. [Example:

struct A { int x(); };
struct B : A { };
struct C : A {
  using A::x;
  int x(int);
};

struct D : B, C {
  using C::x;
  int x(double);
};
int f(D* d) {
  return d->x();    // error: overload resolution selects A​::​x, but A is an ambiguous base class
}

end example] ]end note

Синоним, созданный a, using-declarationимеет обычную доступность для a member-declaration. Объект, using-declaratorкоторый называет конструктор, не создает синоним; вместо этого дополнительные конструкторы доступны, если они будут доступны при использовании для создания объекта соответствующего базового класса, а доступность using-declarationигнорируется. [Example:

class A {
private:
    void f(char);
public:
    void f(int);
protected:
    void g();
};

class B : public A {
  using A::f;       // error: A​::​f(char) is inaccessible
public:
  using A::g;       // B​::​g is a public synonym for A​::​g
};

end example]

Если a using-declaratorиспользует ключевое слово typename и указывает зависимое имя ([temp.dep]), имя, введенное с помощью using-declaration, обрабатывается как typedef-name.

A using-declarationс более чем одним using-declaratorэквивалентно соответствующей последовательности using-declarations с одним using-declaratorкаждым.

10.3.4 Using directive [namespace.udir]

using-directive:
	attribute-specifier-seqopt using  namespace nested-name-specifieropt namespace-name ;

A using-directiveне должен появляться в области класса, но может появляться в области пространства имен или в области блока. [ Note: При поиске a namespace-nameв a using-directiveучитываются только имена пространств имен, см [basic.lookup.udir]. ] Необязательный элемент принадлежит к .end noteattribute-specifier-sequsing-directive

A using-directiveуказывает, что имена в назначенном пространстве имен могут использоваться в области, в которой using-directiveпоявляется после using-directive. При unqualified name lookupэтом имена выглядят так, как если бы они были объявлены в ближайшем охватывающем пространстве имен, которое содержит как пространство имен, так using-directiveи назначенное пространство имен. [ Note: В этом контексте «содержит» означает «содержит прямо или косвенно». ]end note

A using-directiveне добавляет элементы в декларативную область, в которой находится. [Example:

namespace A {
  int i;
  namespace B {
    namespace C {
      int i;
    }
    using namespace A::B::C;
    void f1() {
      i = 5;        // OK, C​::​i visible in B and hides A​::​i
    }
  }
  namespace D {
    using namespace B;
    using namespace C;
    void f2() {
      i = 5;        // ambiguous, B​::​C​::​i or A​::​i?
    }
  }
  void f3() {
    i = 5;          // uses A​::​i
  }
}
void f4() {
  i = 5;            // ill-formed; neither i is visible
}

end example]

Для получения unqualified lookup, то using-directiveтранзитивность: если сфера содержит , using-directiveчто выдвигает второе пространство имен , которое само по себе содержит using-directives, эффект , как если бы using-directives из второго пространства имен также появилась в первом. [ Note: Для квалифицированного поиска см [namespace.qual]. ] [ end noteExample:

namespace M {
  int i;
}

namespace N {
  int i;
  using namespace M;
}

void f() {
  using namespace N;
  i = 7;            // error: both M​::​i and N​::​i are visible
}

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

namespace A {
  int i;
}
namespace B {
  int i;
  int j;
  namespace C {
    namespace D {
      using namespace A;
      int j;
      int k;
      int a = i;    // B​::​i hides A​::​i
    }
    using namespace D;
    int k = 89;     // no problem yet
    int l = k;      // ambiguous: C​::​k or D​::​k
    int m = i;      // B​::​i hides A​::​i
    int n = j;      // D​::​j hides B​::​j
  }
}

end example]

Если пространство имен находится extended после a using-directiveдля этого пространства имен, дополнительные члены расширенного пространства имен и члены пространств имен, назначенные using-directives в расширении, namespace-definitionмогут использоваться после расширения namespace-definition.

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

namespace A {
  class X { };
  extern "C"   int g();
  extern "C++" int h();
}
namespace B {
  void X(int);
  extern "C"   int g();
  extern "C++" int h(int);
}
using namespace A;
using namespace B;

void f() {
  X(1);             // error: name X found in two namespaces
  g();              // OK: name g refers to the same entity
  h();              // OK: overload resolution selects A​::​h
}

end note]

Во время разрешения перегрузки все функции из транзитивного поиска рассматриваются для сопоставления аргументов. Набор объявлений, найденных при переходном поиске, неупорядочен. [ Note: В частности, порядок, в котором рассматривались пространства имен, и отношения между пространствами имен, подразумеваемые using-directives элементом, не приводят к тому, что предпочтение отдается никаким объявлениям, найденным в результате поиска. ] Двусмысленность существует, если наилучшее соответствие находит две функции с одинаковой сигнатурой, даже если одна находится в пространстве имен, доступном через пространство имен другой. [end noteusing-directives 99Example:

namespace D {
  int d1;
  void f(char);
}
using namespace D;

int d1;             // OK: no conflict with D​::​d1

namespace E {
  int e;
  void f(int);
}

namespace D {       // namespace extension
  int d2;
  using namespace E;
  void f(int);
}

void f() {
  d1++;             // error: ambiguous ​::​d1 or D​::​d1?
  ::d1++;           // OK
  D::d1++;          // OK
  d2++;             // OK: D​::​d2
  e++;              // OK: E​::​e
  f(1);             // error: ambiguous: D​::​f(int) or E​::​f(int)?
  f('a');           // OK: D​::​f(char)
}

end example]

Во время поиска имени в иерархии классов некоторые двусмысленности могут быть разрешены путем рассмотрения того, скрывает ли один член другого на некоторых путях ([class.member.lookup]). При рассмотрении набора имен, найденных в результате следования, такого разрешения неоднозначности нет using-directives.