2012-03-26 5 views
3

g ++ 4.4.6を使用してうまく動作するが、Visual Studio 2008を使用してコンパイルできない以下のコードがあります。引数依存ルックアップと関連しているようですので、g ++が正しいと思います。コンパイルusingディレクティブはC++の関数引数にどのように影響しますか?

// testClass.hpp 
namespace test { 
    class foo { 
     public: 
     foo(){} 
    }; 

    class usesFoo { 
     public: 
     usesFoo() {} 

     void memberFunc(foo &input); 
    }; 
} 

// testClass.cpp 
#include "testClass.hpp" 

using test::usesFoo; 

void usesFoo::memberFunc(foo &input) { 
    (void) input; 
} 

のVisual Studioにされたコンパイルするとき、私は取得エラー、

1> ...
1> testClass.cpp 1> C:\作業\ testproject \ testproject \ testclass.cpp C2065: '入力':宣言されていない識別子 1> c:\ work \ testproject(6):エラーC2065: 'foo':宣言されていない識別子 1> c:\ work \ testproject \ testproject \ testclass.cpp \ testproject \ testclass.cpp(6):エラーC2448: 'test :: usesFoo :: memberFunc':関数スタイルの初期化子が関数定義のように見える

私は、cppファイルのメンバ関数に名前空間を直接置くか、 "namespace testを使う"のどちらかが問題を解決するかどうかを知っています。

+1

あなたのコードがコンパイルされることを期待する理由はありません。 fooはusesFooで定義されていません。それはg ++でコンパイルされて興味深いです。 –

+2

'memberFunc'は静的ではなく、' foo'は修飾されていません。 *引数*依存ルックアップは、*関数*の名前が引数の名前空間内で検索されることを意味し、他の方法では検索されません。 –

+0

+1のコメント –

答えて

1

コードは正しいですが、引数に依存するルックアップとは関係ありません。また、using宣言は、fooではなく、usesFooという結果にのみ影響します。クラスメンバーの名前を一度発話すると、このクラスのコンテキストで他の名前が検索されます。 fooはtest :: usesFoo`のメンバーです。

void test::usesFoo::memberFunction(foo& input) { 
    (void)input; 
} 

このため、関連する句は3.4.1非修飾名のルックアップ[basic.lookup.unqual]段落6:usingディレクティブがなければ、あなたはこのようなメンバ関数を定義する必要があるだろう

名前空間Nのメンバである関数のdeclarator-idに続く関数の定義で使用される名前(説明の目的でのみ、Nはグローバルスコープを表すことができる)は、ブロックが使用されているか、その囲みブロックの一つ(6.3)で使用されているか、または名前空間Nで使用される前に宣言されなければならず、Nがネストされた名前空間である場合、 Nは名前空間を囲んでいます。

引数依存ルックアップは、関数が呼び出されたときにのみ表示され、定義時には表示されません。これらのことは、お互いに何の関係もありません。