2012-05-01 12 views
7

Czy funkcje w obrębie przestrzeni nazw nie powinny być dostępne tylko za pomocą zakresu nazw lub dyrektywy użytkowania?Dlaczego niektóre funkcje w przestrzeni nazw są dostępne bez prefiksu zakresu przestrzeni nazw?

Mam problem z tym, że niektóre funkcje zdefiniowane w przestrzeni nazw są dostępne poza tą przestrzenią nazw. Uważam, że powinien wystąpić błąd kompilatora, ale nie dostaję żadnego z trzech różnych kompilatorów, które wypróbowałem (VS.NET 2003, VS2010 i GCC 4).

Oto kod:

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! 
} 

Żadne funkcje powinny być dostępne bez użycia N :: prefiks, ale C, D i E są z jakiegoś nieznanego powodu. Początkowo myślałem, że to błąd kompilatora, ale ponieważ widzę to w wielu kompilatorach, to mam wątpliwości co do tego, co się dzieje.

+0

Myślałem, że to był "stary błąd kompilatora", ale to również kompiluje na gcc 4.6. – mfontanini

+0

Domyślam się, że masz następujące linie: 'using N :: some_type;' oraz 'using N :: some_struct;' a typy zwracane C, D i E są tymi typami. – gcochard

+0

Greg, możesz usunąć użytek i nadal się dzieje. Również typy zwrotu wszystkich funkcji są nieważne. – syplex

Odpowiedz

10

Myślę, że widzisz efekt Koenig lookup. W twoim przykładzie foo i s są typy zdefiniowane w przestrzeni nazw N. Twoje połączenia z procedurami C, D i E używają argumentów tych typów, więc przestrzeń nazw N jest przeszukiwana w celu rozwiązania tych wywołań funkcji.

+3

Nota boczna: dodanie nawiasów, tj. '(C) (& foo)', zapobiegnie wyszukiwaniu zależnemu od argumentów. –

+0

Cóż, masz rację. Jest w sekcji 3.4.2 specyfikacji C++ z 2003 roku. Zdaję sobie sprawę, że nie zgadzam się z tą częścią specyfikacji i myślę, że była ona źle pomyślana, ale tak właśnie jest. Czy ktoś wie, czy istnieje sposób na wymuszenie bardziej ścisłego zakresu nazw w GCC lub VC++? – syplex

+0

@ syplex W rzeczywistości jest niezwykle przydatny do poprawnego wyszukiwania wolnych funkcji w oparciu o typy argumentów wewnątrz szablonów. Nie sądzę, że g ++ oferuje taką opcję, ponieważ byłoby sprzeczne z tym, czego wymaga standard. Jaki jest problem * prawdziwy *, który próbujesz rozwiązać tutaj? –

Powiązane problemy