2012-05-01 8 views
7

¿No deberían ser accesibles las funciones dentro de un espacio de nombres usando el ámbito de espacio de nombres o la directiva using?¿Por qué algunas funciones dentro de un espacio de nombres son accesibles sin el prefijo de delimitación del espacio de nombres?

Tengo un problema donde ciertas funciones, definidas dentro de un espacio de nombres, son accesibles FUERA de ese espacio de nombres. Creo que debería haber un error de compilación, pero no estoy obteniendo ninguno en los tres compiladores diferentes que he probado (VS.NET 2003, VS2010 y GCC 4).

Aquí está el código:

namespace N{ 
    typedef struct _some_type *some_type; 
    struct some_struct { int x; }; 
    void A(void); 
    void B(int); 
    void C(some_type*); 
    void D(some_type); 
    void E(struct some_struct); 
} 

using N::some_type; 
using N::some_struct; 

void TestFunction() 
{ 
    some_type foo; 
    some_struct s; 

    N::A();   //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::B(0);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::C(&foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::C(&foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    C(&foo);  //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::D(foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::D(foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    D(foo);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::E(s);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::E(s);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    E(s);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 
} 

Ninguna de las funciones debe ser accesible sin necesidad de utilizar la N :: prefijo, pero C, D, y E son por alguna razón desconocida. Inicialmente pensé que era un error de compilación, pero debido a que estoy viendo esto en varios compiladores, me hace preguntar qué está pasando.

+0

Pensé que esto era un "error del compilador antiguo", pero que también se compila en gcc 4.6. – mfontanini

+0

Mi mejor estimación es el hecho de que tiene estas líneas: 'using N :: some_type;' y 'using N :: some_struct;' y los tipos de retorno de C, D y E son esos tipos. – gcochard

+0

Greg, puedes eliminar los usos y todavía sucede. Además, los tipos de devolución de todas las funciones son nulos. – syplex

Respuesta

10

Creo que está viendo el efecto de Koenig lookup. En su ejemplo, foo y s son tipos definidos en el espacio de nombres N. Sus llamadas a las rutinas C, D y E usan argumentos de esos tipos, por lo que se busca en el espacio de nombres N para resolver esas llamadas a funciones.

+3

Nota al margen: al agregar paréntesis, es decir '(C) (& foo)' evitará la búsqueda dependiente del argumento. –

+0

Bueno, estás en lo cierto. Está en la sección 3.4.2 de la especificación 2003 C++. Sucede que estoy en desacuerdo con esta parte de la especificación y creo que fue mal concebida, pero ahí está. ¿Alguien sabe si hay una manera de forzar un alcance del espacio de nombres más estricto en GCC o VC++? – syplex

+0

@syplex De hecho, es extremadamente útil para buscar funciones libres según los tipos de argumentos dentro de las plantillas. No creo que g ++ ofrezca esta opción, ya que iría en contra de lo que exige el estándar. ¿Cuál es el problema * real * que estás tratando de resolver aquí? –

Cuestiones relacionadas