2012-05-01 17 views
7

名前空間スコープを使用するか、またはusingディレクティブを使用するだけで、名前空間内の関数にアクセスできないようにする必要がありますか?名前空間スコープ接頭辞なしで名前空間内の一部の機能にアクセスできないのはなぜですか?

名前空間の内部で定義された特定の関数がその名前空間の外部からアクセスできるという問題が発生しています。私はコンパイラのエラーがあるはずだと信じていますが、私が試した3つのコンパイラ(VS.NET 2003、VS2010、GCC 4)を渡すことはできません。機能の

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

なしN ::接頭辞を使用せずにアクセスできるべきではありませんが、C、D、およびEは、いくつかの未知の理由である:ここでは

はコードです。私は当初、それがコンパイラのバグだと思っていましたが、これを複数のコンパイラで見ているので、何が起こっているのか疑問に思っています。

+0

これは「古いコンパイラのバグ」だと思っていましたが、gcc 4.6でもコンパイルされていました。 – mfontanini

+0

「N :: some_type;」と「N :: some_struct;」を使用し、C、D、Eの戻り値の型はこれらの型を持っていることを推測してください。 – gcochard

+0

グレッグ、あなたは使用して削除することができ、それでも起こります。また、すべての関数の戻り値の型は無効です。 – syplex

答えて

10

私はあなたがKoenig lookupの効果を見ていると思います。あなたの例では、foosは、名前空間Nで定義されたタイプ です。ルーチンCD、およびEの呼び出しは、これらの型の引数を使用するため、これらの関数呼び出しを解決するために名前空間Nが検索されます。

+3

サイドノート:カッコを追加すると、つまり '(C)(&foo)'は引数に依存する検索を防止します。 –

+0

あなたは正しいです。これは、2003 C++仕様のセクション3.4.2にあります。私は仕様のこの部分に同意せず、それが病気であると思うが、そこにはある。 GCCやVC++でより厳密な名前空間スコープを強制する方法があるのか​​誰にも知られていますか? – syplex

+0

@syplex実際には、テンプレート内の引数の型に基づいてフリー関数を正しく検索するのに非常に便利です。私はg ++が標準で要求されているものに逆らうようなオプションを提供しているとは思わない。ここで解決しようとしている*本当の問題は何ですか? –

関連する問題