2011-02-03 12 views
13

Parece que es imposible declarar un alias de espacio de nombres dentro de una clase; sin embargo, podemos hacerlo en función de nivel (probado con g ++ 4.3.4):¿Por qué no podemos declarar alias de espacio de nombres dentro de una clase?

namespace A 
{ 
} 

class C 
{ 
    namespace N = A; // error: expected unqualified-id before `namespace' 
}; 

class D 
{ 
    void f(); 
}; 

void D::f() 
{ 
    namespace N = A; // OK 
} 

Cualquier idea de por qué existe tal restricción? Esto no parece muy consistente con typedefs que pueden declararse dentro de una clase.

+4

+1, yo no sabía que esto era posible: 'espacio de nombres N = A;' –

+3

@Alexandre supongo que quiere algo parecido a este espacio de nombres 'A = A1 A2 :: :: :: A3 A4; ' –

+4

por cierto +1 ya que esto es nuevo para mí :) –

Respuesta

5

No soy un experto en el estándar C++, pero voy a sacar el cuello e intentar responder a tu pregunta. Supongo que el uso de namespace N = A dentro de una declaración de clase carece de la definición de cómo debe definirse un miembro de la clase.

El C++ estándar define un miembro de la clase como

member-specification: 
    member-declaration member-specification_opt 
    access-specifier : member-specification_opt 
member-declaration: 
    decl-specifier-seq_opt member-declarator-list_opt ; 
    function-definition ;opt 
    ::opt nested-name-specifier templateopt unqualified-id ; 
    using-declaration 
    static_assert-declaration 
    template-declaration 
member-declarator-list: 
    member-declarator 
    member-declarator-list , member-declarator 
member-declarator: 
    declarator pure-specifier_opt 
    declarator constant-initializer_opt 
    identifier_opt : constant-expression 
pure-specifier: 
    = 0 
constant-initializer: 
    = constant-expression 

El punto importante es la = en la declaración, el compilador está a la espera sea un especificador puro o constante inicializador declaración y que la línea no termina en un cero, no estamos aplicando un especificador puro en este caso.

Analizando la declaración namespace N = A el compilador ve esto como

declarator = constant-expression 

Y puesto namespace es una palabra clave que no se puede utilizar.

typedef está permitido porque (de la norma)

tipos anidados son clases y enumeraciones definidas en la clase, y tipos arbitrarios declarados como miembros mediante el uso de una declaración typedef.

+1

Esto es informativo pero no educativo. ¿Por qué el comité tomó esta decisión? eso es lo que quiero saber. Mi apuesta es porque vieron una lata de gusanos causada por ADL. –

6

Según C++ estándar 3.3.6

Las reglas siguientes describen el alcance de nombres declarados en clases.

1) El alcance potencial de un nombre declarado en una clase consiste no solo en la región declarativa que sigue al declarador del nombre, sino también en todos los cuerpos de función, argumentos predeterminados e inicializadores del constructor en esa clase (incluyendo tales cosas en clases anidadas). ...........

Para que solo pueda declarar cosas de esta lista en el alcance de clase. Declarar cualquier otra cosa en el alcance de la clase no es válido. No solo la alianza del espacio de nombres, sino también el espacio de nombres. Por ejemplo

class myClass 
{ 
    //compilation error !!! 
    namespace myNamespace 
    { 
    } 
    using namespace std;//another compilation error 
} 

Editar:

Cualquier idea de por qué existe tal restricción? Esto no parece muy consistente con typedefs que pueden declararse dentro de una clase.

Porque el uso de typedefs en las clases es muy útil (por ejemplo vector<int>::iterator), mientras que para los espacios de nombres es inútil.Considere siguiente código

class myClass 
{ 
    namespce N=std; 
}; 

//now let's use N 
MyClass::N::vector<int> v;//don't you think, that this syntax is horrible, and useless????? 

Para la comparación ver lo que está haciendo en la función

void f() 
{ 
    namespace bnu= boost::numeric::ublas; 
    bnu::matrix<int> m;//and now we can use short name bnu 
} 

Para la clase podemos declarar alianza espacio de nombres en el archivo CPP y hay NO NECESITA a daclare en declaración de la clase.

+0

Ok, no es un ataque personal, pero te equivocas hombre :) usa tu propio ejemplo de 'bnu' y ten en cuenta que ahora puedes usar' bnu' en los argumentos de los métodos 'myClass' que es muy útil, así como valores de retorno (en declaraciones) Además, su redacción en la parte superior 'solo las cosas de esta lista' no tiene sentido, se refiere a las regiones declarativas, no son utilizables. ADEMÁS, puede declarar typedefs y clases internas en el alcance de la clase. así como 'using base :: method' y static_assert. La prohibición de espacios de nombres debe tener otra motivación que esté fuera de todo lo mencionado en esta página. –

3

No estoy de acuerdo con que la declaración del espacio de nombres dentro de una clase sea completamente inútil. Sería útil poder declarar enumeraciones dentro de los espacios de nombres dentro de las clases. Esto le permitiría acceder a los elementos de diferentes matrices con índices lógicos para la matriz específica.

class myClass 
{ 
    private: 
     namespace TransAndRotIdx { 
      enum { U, V, W, P, Q, R }; }; 
     namespace RotIdx { 
      enum { P, Q, R }; }; 
     double tr[6]; 
     double r[3]; 

    public: 
     double getTranslationMag(void) 
     { 
      using namespace TransAndRotIdx; 
      return sqrt(tr[U]*tr[U]+tr[V]*tr[V]+tr[W]*tr[W]); 
     } 
     double getRotationMag(void) 
     { 
      using namespace RotIdx; 
      return sqrt(tr[P]*tr[P]+tr[Q]*tr[Q]+tr[R]*tr[R]); 
     } 
} 
+0

Solo para el registro, en C++ 11 básicamente puedes lograr esto con 'enum class' (pero sin el beneficio de la declaración' using'). – wjl

Cuestiones relacionadas