Namespaces
Variants

Namespaces

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Namespace declaration
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Los espacios de nombres proporcionan un método para prevenir conflictos de nombres en proyectos grandes.

Las entidades declaradas dentro de un bloque de namespace se colocan en un ámbito de namespace, lo que evita que se confundan con entidades de nombre idéntico en otros ámbitos.

Las entidades declaradas fuera de todos los bloques de namespace pertenecen al global namespace . El global namespace pertenece al ámbito global , y puede referirse explícitamente con un :: inicial. Aunque no tiene declaración, el global namespace no es un unnamed namespace .

Se permiten múltiples bloques de namespace con el mismo nombre. Todas las declaraciones dentro de estos bloques se declaran en el mismo ámbito del namespace.

Contenidos

Sintaxis

namespace ns-name { declarations } (1)
inline namespace ns-name { declarations } (2) (desde C++11)
namespace { declarations } (3)
ns-name :: member-name (4)
using namespace ns-name ; (5)
using ns-name :: member-name ; (6)
namespace name = qualified-namespace ; (7)
namespace ns-name :: member-name { declarations } (8) (desde C++17)
namespace ns-name :: inline member-name { declarations } (9) (desde C++20)
1) Definición de espacio de nombres con nombre para el espacio de nombres ns-name .
2) Definición de espacio de nombres en línea para el espacio de nombres ns-name . Las declaraciones dentro de ns-name serán visibles en su espacio de nombres contenedor.
3) Definición de espacio de nombres sin nombre . Sus miembros tienen alcance potencial desde su punto de declaración hasta el final de la unidad de traducción, y tienen enlace interno .
4) Los nombres de espacio de nombres (junto con los nombres de clase) pueden aparecer en el lado izquierdo del operador de resolución de ámbito, como parte de la búsqueda de nombre calificada .
5) using-directive : Desde el punto de vista de la búsqueda de nombres no calificados name lookup de cualquier nombre después de una using-directive y hasta el final del ámbito en el que aparece, cada nombre del ns-name es visible como si estuviera declarado en el espacio de nombres envolvente más cercano que contiene tanto la using-directive como el ns-name .
6) using-declaration : hace que el símbolo member-name del espacio de nombres ns-name sea accesible para la búsqueda no calificada como si estuviera declarado en el mismo ámbito de clase, ámbito de bloque o espacio de nombres donde aparece esta declaración using.
namespace-alias-definition : convierte a name en un sinónimo de otro espacio de nombres: ver namespace alias
8) definición de espacio de nombres anidado: namespace A :: B :: C { ... } es equivalente a namespace A { namespace B { namespace C { ... } } } .
9) definición de espacio de nombres en línea anidado: namespace A :: B :: inline C { ... } es equivalente a namespace A :: B { inline namespace C { ... } } . inline puede aparecer delante de cada nombre de espacio de nombres excepto el primero: namespace A :: inline B :: C { } es equivalente a namespace A { inline namespace B { namespace C { } } } .

Explicación

Espacios de nombres

inline (opcional) namespace attr  (opcional) identifier { namespace-body }
inline - (desde C++11) si está presente, convierte esto en un espacio de nombres en línea (ver abajo). No puede aparecer en la definición de espacio de nombres de extensión si la definición de espacio de nombres original no utilizó inline
attr - (desde C++17) secuencia opcional de cualquier número de atributos
identifier - ya sea
  • un identificador no utilizado previamente, en cuyo caso esto es una definición de espacio de nombres original ;
  • el nombre de un espacio de nombres, en cuyo caso esto es una definición de espacio de nombres de extensión ;
  • una secuencia de especificadores de espacio de nombres envolventes separados por :: , terminando con identifier , en cuyo caso esto es una definición de espacio de nombres anidado
(desde C++17)
namespace-body - secuencia posiblemente vacía de declaraciones de cualquier tipo (incluyendo definiciones de clases y funciones así como espacios de nombres anidados)

Las definiciones de espacio de nombres solo están permitidas en el ámbito del espacio de nombres, incluido el ámbito global.

Para reabrir un espacio de nombres existente (formalmente, para ser una definición de espacio de nombres de extensión ), la búsqueda del identificador utilizado en la definición del espacio de nombres debe resolverse a un nombre de espacio de nombres (no un alias de espacio de nombres), que fue declarado como miembro del espacio de nombres envolvente o de un espacio de nombres inline dentro de un espacio de nombres envolvente.

El namespace-body define un namespace scope , que afecta el name lookup .

Todos los nombres introducidos por las declaraciones que aparecen dentro del namespace-body (incluyendo definiciones de espacios de nombres anidados) se convierten en miembros del espacio de nombres identifier , ya sea que esta definición del espacio de nombres sea la definición original (que introdujo el identifier ), o una definición de extensión del espacio de nombres (que "reabrió" el espacio de nombres ya definido)

Un miembro de espacio de nombres que fue declarado dentro de un cuerpo de espacio de nombres puede ser definido o redeclarado fuera de él usando calificación explícita

namespace Q
{
    namespace V   // V es un miembro de Q, y está completamente definido dentro de Q
    { // namespace Q::V { // Alternativa de C++17 a las líneas anteriores
        class C { void m(); }; // C es un miembro de V y está completamente definido dentro de V
                               // C::m solo está declarado
        void f(); // f es un miembro de V, pero solo está declarado aquí
    }
    void V::f() // definición del miembro f de V fuera de V
                // los espacios de nombres envolventes de f siguen siendo el espacio de nombres global, Q y Q::V
    {
        extern void h(); // Esto declara ::Q::V::h
    }
    void V::C::m() // definición de V::C::m fuera del espacio de nombres (y del cuerpo de la clase)
                   // los espacios de nombres envolventes son el espacio de nombres global, Q y Q::V
    {}
}

Las definiciones y redeclaraciones fuera del espacio de nombres solo están permitidas

  • después del punto de declaración,
  • en el ámbito del espacio de nombres, y
  • en espacios de nombres que engloban el espacio de nombres original (incluyendo el espacio de nombres global).

Además, deben usar la sintaxis de identificador calificado.

namespace Q
{
    namespace V    // definición de espacio de nombres original para V
    {
        void f();  // declaración de Q::V::f
    }
    void V::f() {} // Correcto
    void V::g() {} // Error: g() aún no es miembro de V
    namespace V    // definición de extensión de espacio de nombres para V
    {
        void g();  // declaración de Q::V::g
    }
}
namespace R           // no es un espacio de nombres envolvente para Q
{
    void Q::V::g() {} // Error: no se puede definir Q::V::g dentro de R
}
void Q::V::g() {}     // Correcto: el espacio de nombres global envuelve a Q

Los nombres introducidos por las declaraciones friend dentro de una clase no local X se convierten en miembros del namespace de inclusión más interno de X, pero no se vuelven visibles para la búsqueda de nombres ordinaria (ni no calificada ni calificada ) a menos que se proporcione una declaración coincidente en el ámbito del namespace, ya sea antes o después de la definición de la clase. Dicho nombre puede encontrarse mediante ADL que considera tanto namespaces como clases.

Solo el espacio de nombres envolvente más interno es considerado por dicha declaración de amistad al decidir si el nombre entraría en conflicto con un nombre previamente declarado.

void h(int);
namespace A
{
    class X
    {
        friend void f(X);       // A::f es un amigo
        class Y
        {
            friend void g();    // A::g es un amigo
            friend void h(int); // A::h es un amigo, sin conflicto con ::h
        };
    };
    // A::f, A::g y A::h no son visibles en el ámbito del namespace
    // aunque son miembros del namespace A
    X x;
    void g()  // definición de A::g
    {
        f(x); // A::X::f se encuentra mediante ADL
    }
    void f(X) {}   // definición de A::f
    void h(int) {} // definición de A::h
    // A::f, A::g y A::h ahora son visibles en el ámbito del namespace
    // y también son amigos de A::X y A::X::Y
}

Espacios de nombres en línea

Un espacio de nombres en línea es un espacio de nombres que utiliza la palabra clave opcional inline en su definición-de-espacio-de-nombres-original .

Los miembros de un espacio de nombres en línea se tratan como si fueran miembros del espacio de nombres que los contiene en muchas situaciones (enumeradas a continuación). Esta propiedad es transitiva: si un espacio de nombres N contiene un espacio de nombres en línea M, que a su vez contiene un espacio de nombres en línea O, entonces los miembros de O pueden usarse como si fueran miembros de M o N.

  • Una directiva-using que nombra el espacio de nombres en línea se inserta implícitamente en el espacio de nombres contenedor (similar a la directiva using implícita para el espacio de nombres sin nombre)
  • En la búsqueda dependiente de argumento , cuando se agrega un espacio de nombres al conjunto de espacios de nombres asociados, sus espacios de nombres en línea también se agregan, y si se agrega un espacio de nombres en línea a la lista de espacios de nombres asociados, su espacio de nombres contenedor también se agrega.
  • Cada miembro de un espacio de nombres en línea puede ser parcialmente especializado, explícitamente instanciado o explícitamente especializado como si fuera un miembro del espacio de nombres contenedor.
  • La búsqueda de nombres calificada que examina el espacio de nombres contenedor incluirá los nombres de los espacios de nombres en línea incluso si el mismo nombre está presente en el espacio de nombres contenedor.
// in C++14, std::literals and its member namespaces are inline
{
    using namespace std::string_literals; // makes visible operator""s 
                                          // from std::literals::string_literals
    auto str = "abc"s;
}
{
    using namespace std::literals; // makes visible both
                                   // std::literals::string_literals::operator""s
                                   // and std::literals::chrono_literals::operator""s
    auto str = "abc"s;
    auto min = 60s;
}
{
    using std::operator""s; // makes both std::literals::string_literals::operator""s
                            // and std::literals::chrono_literals::operator""s visible
    auto str = "abc"s;
    auto min = 60s;
}

Nota: la regla sobre especializaciones permite el versionado de bibliotecas: diferentes implementaciones de una plantilla de biblioteca pueden definirse en diferentes espacios de nombres en línea, mientras se permite al usuario extender el espacio de nombres principal con una especialización explícita de la plantilla primaria:

namespace Lib
{
    inline namespace Lib_1
    {
        template<typename T> class A; 
    }
    template<typename T> void g(T) { /* ... */ }
}
/* ... */
struct MyClass { /* ... */ };
namespace Lib
{
    template<> class A<MyClass> { /* ... */ };
}
int main()
{
    Lib::A<MyClass> a;
    g(a);  // ok, Lib is an associated namespace of A
}
(desde C++11)

Espacios de nombres sin nombre

La unnamed-namespace-definition es una definición de espacio de nombres de la forma

inline (opcional) namespace attr  (opcional) { namespace-body }
inline - (since C++11) si está presente, convierte esto en un namespace inline
attr - (since C++17) secuencia opcional de cualquier número de attributes

Esta definición se trata como una definición de un espacio de nombres con nombre único y una using-directive en el ámbito actual que nombra este espacio de nombres sin nombre (Nota: la directiva using implícitamente añadida hace que el espacio de nombres esté disponible para la búsqueda calificada de nombres y la búsqueda no calificada de nombres , pero no para la búsqueda dependiente de argumentos ). El nombre único es exclusivo en todo el programa, pero dentro de una unidad de traducción cada definición de espacio de nombres sin nombre se asigna al mismo nombre único: múltiples definiciones de espacios de nombres sin nombre en el mismo ámbito denotan el mismo espacio de nombres sin nombre.

namespace
{
    int i; // define ::(unique)::i
}
void f()
{
    i++;   // incrementa ::(unique)::i
}
namespace A
{
    namespace
    {
        int i;        // A::(unique)::i
        int j;        // A::(unique)::j
    }
    void g() { i++; } // A::(unique)::i++
}
using namespace A; // introduce todos los nombres de A en el espacio de nombres global
void h()
{
    i++;    // error: ::(unique)::i y ::A::(unique)::i están ambos en el ámbito
    A::i++; // ok, incrementa ::A::(unique)::i
    j++;    // ok, incrementa ::A::(unique)::j
}

Aunque los nombres en un espacio de nombres sin nombre pueden declararse con enlace externo, nunca son accesibles desde otras unidades de traducción porque su nombre de espacio de nombres es único.

(until C++11)

Los espacios de nombres sin nombre, así como todos los espacios de nombres declarados directa o indirectamente dentro de un espacio de nombres sin nombre, tienen enlace interno , lo que significa que cualquier nombre que se declare dentro de un espacio de nombres sin nombre tiene enlace interno.

(since C++11)

Declaraciones using

Introduce un nombre que está definido en otro lugar en la región declarativa donde aparece esta declaración using.

using typename (opcional) especificador-de-nombre-anidado identificador-no-calificado ; (hasta C++17)
using lista-de-declaradores ; (desde C++17)
typename - la palabra clave typename puede utilizarse según sea necesario para resolver nombres dependientes , cuando la declaración using introduce un tipo miembro de una clase base en una plantilla de clase
nested-name-specifier - una secuencia de nombres y operadores de resolución de ámbito :: , que termina con un operador de resolución de ámbito. Un único :: se refiere al espacio de nombres global.
unqualified-id - una expresión de identificación
declarator-list - lista separada por comas de uno o más declaradores de la forma typename (opcional) nested-name-specifier unqualified-id . Un declarador puede ir seguido de puntos suspensivos para indicar expansión de paquete , aunque esa forma solo tiene sentido en definiciones de clases derivadas

Las declaraciones using pueden utilizarse para introducir miembros de espacio de nombres en otros espacios de nombres y ámbitos de bloque, o para introducir miembros de clase base en definiciones de clases derivadas , o para introducir enumerators en espacios de nombres, bloques y ámbitos de clase (since C++20) .

Una declaración using con más de un using-declarator es equivalente a una secuencia correspondiente de declaraciones using con un using-declarator.

(desde C++17)

Para el uso en definiciones de clases derivadas, consulte using declaration .

Los nombres introducidos en un ámbito de espacio de nombres mediante una declaración using pueden usarse como cualquier otro nombre, incluyendo la búsqueda calificada desde otros ámbitos:

void f();
namespace A
{
    void g();
}
namespace X
{
    using ::f;        // f global ahora es visible como ::X::f
    using A::g;       // A::g ahora es visible como ::X::g
    using A::g, A::g; // (C++17) OK: declaración doble permitida en ámbito de namespace
}
void h()
{
    X::f(); // llama a ::f
    X::g(); // llama a A::g
}

Si, después de que se utilizó la declaración using para tomar un miembro de un espacio de nombres, el espacio de nombres se extiende y se introducen declaraciones adicionales para el mismo nombre, esas declaraciones adicionales no se vuelven visibles a través de la declaración using (a diferencia de la directiva using). Una excepción es cuando una declaración using nombra una plantilla de clase: las especializaciones parciales introducidas posteriormente son efectivamente visibles, porque su lookup procede a través de la plantilla primaria.

namespace A
{
    void f(int);
}
using A::f; // ::f es ahora un sinónimo de A::f(int)
namespace A       // extensión del namespace
{
    void f(char); // no cambia lo que significa ::f
}
void foo()
{
    f('a'); // llama a f(int), aunque exista f(char).
}
void bar()
{
    using A::f; // esta f es un sinónimo tanto para A::f(int) como para A::f(char)
    f('a');     // llama a f(char)
}

Las declaraciones using no pueden nombrar template-id , o un namespace , o un enumerador con ámbito (hasta C++20) . Cada declarador en una declaración using introduce uno y solo un nombre, por ejemplo la declaración using para una enumeración no introduce ninguno de sus enumeradores.

Todas las restricciones sobre declaraciones regulares de los mismos nombres, ocultamiento y reglas de sobrecarga se aplican a las declaraciones using:

namespace A
{
    int x;
}
namespace B
{
    int i;
    struct g {};
    struct x {};
    void f(int);
    void f(double);
    void g(char); // OK: el nombre de función g oculta la estructura g
}
void func()
{
    int i;
    using B::i;   // error: i declarada dos veces
    void f(char);
    using B::f;   // OK: f(char), f(int), f(double) son sobrecargas
    f(3.5);       // llama a B::f(double)
    using B::g;
    g('a');       // llama a B::g(char)
    struct g g1;  // declara que g1 tiene tipo struct B::g
    using B::x;
    using A::x;   // OK: oculta la estructura B::x
    x = 99;       // asigna a A::x
    struct x x1;  // declara que x1 tiene tipo struct B::x
}

Si una función fue introducida por una declaración using, declarar una función con el mismo nombre y lista de parámetros está mal formado (a menos que la declaración sea para la misma función). Si una plantilla de función fue introducida por una declaración using, declarar una plantilla de función con el mismo nombre, lista de tipos de parámetros, tipo de retorno y lista de parámetros de plantilla está mal formado. Dos declaraciones using pueden introducir funciones con el mismo nombre y lista de parámetros, pero si se intenta una llamada a esa función, el programa está mal formado.

namespace B
{
    void f(int);
    void f(double);
}
namespace C
{
    void f(int);
    void f(double);
    void f(char);
}
void h()
{
    using B::f;  // introduce B::f(int), B::f(double)
    using C::f;  // introduce C::f(int), C::f(double), y C::f(char)
    f('h');      // llama a C::f(char)
    f(1);        // error: ¿B::f(int) o C::f(int)?
    void f(int); // error: f(int) entra en conflicto con C::f(int) y B::f(int)
}

Si una entidad es declarada, pero no definida en algún espacio de nombres interno, y luego es declarada mediante una using-declaration en el espacio de nombres externo, y luego aparece una definición en el espacio de nombres externo con el mismo nombre no calificado, esa definición es un miembro del espacio de nombres externo y entra en conflicto con la using-declaration:

namespace X
{
    namespace M
    {
        void g(); // declara, pero no define X::M::g()
    }
    using M::g;
    void g();     // Error: intento de declarar X::g que entra en conflicto con X::M::g()
}

En términos más generales, una declaración que aparece en cualquier ámbito de espacio de nombres e introduce un nombre usando un identificador no calificado siempre introduce un miembro en el espacio de nombres en el que se encuentra y no en ningún otro espacio de nombres. Las excepciones son las instanciaciones explícitas y las especializaciones explícitas de una plantilla principal que se define en un espacio de nombres en línea: debido a que no introducen un nuevo nombre, pueden usar un unqualified-id en un espacio de nombres envolvente.

Directivas using

Una using-directive es una block-declaration con la siguiente sintaxis:

attr  (opcional) using namespace nested-name-specifier  (opcional) namespace-name ; (1)
attr - (since C++11) cualquier número de attributes que se aplican a esta directiva using
nested-name-specifier - una secuencia de nombres y operadores de resolución de ámbito :: , terminando con un operador de resolución de ámbito. Un único :: se refiere al espacio de nombres global. Al buscar los nombres en esta secuencia, lookup considera solo declaraciones de espacios de nombres
namespace-name - un nombre de un espacio de nombres. Al buscar este nombre, lookup considera solo declaraciones de espacios de nombres

Las directivas using están permitidas únicamente en el ámbito de espacio de nombres scope y en ámbito de bloque. Desde el punto de vista de la búsqueda de nombres no calificada de cualquier nombre después de una directiva using y hasta el final del ámbito en el que aparece, cada nombre del namespace-name es visible como si estuviera declarado en el espacio de nombres envolvente más cercano que contiene tanto la directiva using como el namespace-name .

La directiva using no añade ningún nombre a la región declarativa en la que aparece (a diferencia de la declaración using), y por lo tanto no impide que se declaren nombres idénticos.

Las directivas using son transitivas para los propósitos de la búsqueda no calificada : si un ámbito contiene una directiva using que nombra un namespace-name , que a su vez contiene directivas using para algún namespace-name-2 , el efecto es como si las directivas using del segundo espacio de nombres aparecieran dentro del primero. El orden en que ocurren estos espacios de nombres transitivos no influye en la búsqueda de nombres.

namespace A
{
    int i;
}
namespace B
{
    int i;
    int j;
    namespace C
    {
        namespace D
        {
            using namespace A;
            // Los nombres de A son "inyectados" en D.
            // La búsqueda no calificada dentro de D considera estos nombres con el mismo
            // ámbito que el ámbito global (por ejemplo, para propósitos de ocultamiento de nombres).
            // La búsqueda calificada que se refiere a D (D::nombre para algún nombre)
            // encontrará el mismo nombre que la búsqueda no calificada dentro de D.
            int j;
            int k;
            int a = i;   // i es B::i, porque A::i está oculto por B::i
            int b = ::i; // error: todavía no existe i en el espacio de nombres global
        }
        using namespace D; // los nombres de D y A son inyectados en C
        int k = 89; // OK declarar un nombre idéntico a uno introducido por un using
        int l = k;  // ambiguo: C::k o D::k
        int m = i;  // ok: B::i oculta A::i
        int n = j;  // ok: D::j oculta B::j
    }
}
// Todas estas son definiciones equivalentes:
int t0 = B::i;
int t1 = B::C::a;
int t2 = B::C::D::a;

Si, después de que se utilizó una directiva using para nominar algún espacio de nombres, el espacio de nombres se extiende y se añaden miembros adicionales y/o directivas using a él, esos miembros adicionales y los espacios de nombres adicionales son visibles a través de la directiva using (en contraste con la declaración using)

namespace D
{
    int d1;
    void f(char);
}
using namespace D; // introduce D::d1, D::f, D::d2, D::f,
                   // E::e y E::f en el espacio de nombres global
int d1;            // OK: no hay conflicto con D::d1 al declarar
namespace E
{
    int e;
    void f(int);
}
namespace D            // extensión del espacio de nombres
{
    int d2;
    using namespace E; // directiva using transitiva
    void f(int);
}
void f()
{
    d1++;    // error: ¿ambiguo ::d1 o D::d1?
    ::d1++;  // OK
    D::d1++; // OK
    d2++;    // OK, d2 es D::d2
    e++;     // OK: e es E::e debido al using transitivo
    f(1);    // error: ambiguo: ¿D::f(int) o E::f(int)?
    f('a');  // OK: la única f(char) es D::f(char)
}

Notas

La directiva using using namespace std ; en cualquier ámbito de espacio de nombres introduce cada nombre del espacio de nombres std en el espacio de nombres global (dado que el espacio de nombres global es el espacio de nombres más cercano que contiene tanto std como cualquier espacio de nombres declarado por el usuario), lo que puede llevar a colisiones de nombres no deseadas. Esta, y otras directivas using, generalmente se consideran mala práctica en el ámbito de archivo de un archivo de cabecera ( SF.7: No escribas using namespace en el ámbito global en un archivo de cabecera ).

Macro de prueba de características Valor Std Característica
__cpp_namespace_attributes 201411L (C++17) Atributos para espacios de nombres

Palabras clave

namespace , using , inline

Ejemplo

Este ejemplo muestra cómo usar un namespace para crear una clase que ya ha sido nombrada en el std namespace.

#include <vector>
namespace vec
{
    template<typename T>
    class vector
    {
        // ...
    };
} // of vec
int main()
{
    std::vector<int> v1; // Standard vector.
    vec::vector<int> v2; // User defined vector.
    // v1 = v2;          // Error: v1 and v2 are different object's type.
    {
        using namespace std;
        vector<int> v3;  // Same as std::vector
        v1 = v3; // OK
    }
    {
        using vec::vector;
        vector<int> v4;  // Same as vec::vector
        v2 = v4; // OK
    }
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 101 C++98 el programa está mal formado si una declaración de función en ámbito
de espacio de nombres o ámbito de bloque y una función introducida por una
declaración using declaran la misma función (sin ambigüedad)
permitido
CWG 373 C++98 la búsqueda solo consideraba declaraciones de espacio de nombres para
el último nombre en el operando de una directiva using (lo cual es
subóptimo, porque las clases no pueden contener espacios de nombres)
la restricción de búsqueda
se aplica a todos los nombres en los
operandos de directivas using
CWG 460 C++98 una declaración using podía nombrar un espacio de nombres prohibido
CWG 565 C++98 una declaración using no puede introducir una función
idéntica a otra función en el mismo ámbito, pero
la restricción no se aplicaba a plantillas de función
aplicar la misma restricción
también a plantillas de función
CWG 986 C++98 la directiva using era transitiva para búsqueda calificada solo transitiva para búsqueda no calificada
CWG 987 C++98 las entidades declaradas en un espacio de nombres anidado eran
también miembros del espacio de nombres contenedor
ámbitos anidados excluidos
CWG 1021 C++98 no estaba claro si una entidad cuya definición
se introduce a un espacio de nombres mediante declaración using
se considera definida en ese espacio de nombres
no definida en ese espacio de nombres
CWG 1838 C++98 la definición no calificada en un espacio de nombres externo
podría definir una entidad declarada, pero no definida en
otro espacio de nombres e incorporada mediante using
la definición no calificada
siempre se refiere a
su espacio de nombres
CWG 2155 C++98 la resolución de CWG issue 1838 no se
aplicaba a declaraciones de clase y enumeración
aplicada

Véase también

namespace alias crea un alias de un espacio de nombres existente