10 Declarations [dcl.dcl]

10.3 Namespaces [basic.namespace]

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-declaratorinherits 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каждым.