2013-08-08 9 views
7

ネストされたネームスペースとテンプレートクラスを含む問題があります。実際のコードと同じエラーを生成するテストケースを作成することもできましたが、もう少し読みやすいです。 2010プラットフォームツールセットでVS2012を使用して、次のコードをコンパイルネストされた名前空間とあいまいなシンボル

は、エラーが発生します。

namespace A 
{ 
    namespace B 
    { 
     namespace C1 
     { 
     struct SMeasResult{}; 
     } 
     namespace C2 
     { 
     struct SMeasResult{}; 
     } 
    } 
} 

namespace C1Test 
{ 
    using namespace A::B::C1; 

    template<typename T> 
    class Fook 
    { 
    public: 

     void Yu() 
     { 
     SMeasResult Field; 
     } 
    }; 
} 

namespace C2Test 
{ 
    using namespace A::B::C2; 

    template<typename T> 
    class Fook 
    { 
    public: 

     void Yu() 
     { 
     SMeasResult Field; 
     } 
    }; 
} 

void m(){ 
    C1Test::Fook<int> yu; 
    C2Test::Fook<int> me; 

    yu.Yu(); 
    me.Yu(); 
} 

次のように特定のエラーは、次のとおりです。

1>------ Build started: Project: MultiVicomTest (Visual Studio 2010), Configuration: Debug Win32 ------ 
1> test.cpp 
1>c:\code\test.cpp(27): warning C4101: 'Field' : unreferenced local variable 
1>   c:\code\test.cpp(26) : while compiling class template member function 'void C1Test::Fook<T>::Yu(void)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   c:\code\test.cpp(49) : see reference to class template instantiation 'C1Test::Fook<T>' being compiled 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>c:\code\test.cpp(43): error C2872: 'SMeasResult' : ambiguous symbol 
1>   could be 'c:\code\test.cpp(11) : A::B::C2::SMeasResult' 
1>   or  'c:\code\test.cpp(7) : A::B::C1::SMeasResult' 
1>   c:\code\test.cpp(42) : while compiling class template member function 'void C2Test::Fook<T>::Yu(void)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   c:\code\test.cpp(50) : see reference to class template instantiation 'C2Test::Fook<T>' being compiled 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

なぜシンボル私は理解していない「SMeasResult」別の名前空間で使用されるため、コンパイラにあいまいです。 これまでにわかったことは、クラスがテンプレートクラスである場合にのみこの問題が発生することです。テンプレート定義を削除しても同じ問題は発生しません。

私は何か間違ったことを誰かに教えてもらえますか?

+1

私はこれがバグだと確信しています。 Gccとclangはこれをうまくコンパイルして、どうしてそれがあいまいであるのかわかりません。 – jrok

+1

MSVCは、C++ 98以来、言語標準で規定されているように、テンプレートで使用される名前の2段階ルックアップを実装していません。このバグはその可能性が最も高いです。 – Casey

答えて

2

これは実際に私にとってコンパイラのバグのようです。関数のC1Testバージョンがあいまいさなくコンパイルされていると考えると、namespace C1Testの名前空間をどうにかしてC2Test名前空間にも残っていると思われます。

これは、g ++ 4.4と4.5がどちらもこのコードをうまくコンパイルできるという事実によってさらに裏付けられています。

+1

うん、使用は、g ++ではなく、ビジュアルでリークされます。私はこのキーワードの大ファンではないので、私はこの基準が何を言っているのか分かりません。 – Uman

+1

興味深いことに、 'C1Test'の前に名前空間' C2Test'でコードを並べ替えると、 'C2Test'内の' SMeasResult'のために "あいまいさ" *がまだ報告されています。 「C1」の宣言が「C2」の前に現れるという事実は、使用の順序付けよりも重要であると思われる。 – Casey

+0

私の間違い - 重要なのは、どのような宣言でもないテンプレートのインスタンス化の順序です。インスタンス化される2番目のテンプレートは、C1、C2、C1TestまたはC2Testの宣言順序にかかわらず、エラーのために "非難"されます。 – Casey

0

A :: B :: C1 :: SMeasResultを使用してください。 および A :: B :: C2 :: SMeasResultを使用します。 C1TestとC2Testの名前空間には があります。これは問題を解決します。

BTW なぜ多くの名前空間が必要ですか? STLは非常に大きいですが、1つの名前空間しか使用しません。

+0

ブーストも大きく、名前空間もたくさん使用しています; –

+0

この特定のケースでは、さまざまな種類の無線技術に関連するコードを含む大きなコードベースがあります。対応するクラスを、それらが表すテクノロジーに似ている名前空間に移動したいので、多くの名前空間が必要です。他の多くのプラットフォーム(.NET、Java)も同様に統合されているため、それらのプラットフォームと同様の方法を選択しました(これらのプラットフォームでは膨大な名前空間について考えてください)。 – Simon

関連する問題