2012-03-15 18 views
6

のVisual Studio 2010 SP1の使用:これはVC++ 2010コンパイラのバグですか?

1>C:\apps\MVS10\VC\include\vector(609): error C2593: 'operator !=' is ambiguous 
1>   C:\apps\MVS10\VC\include\xmemory(268): could be 'bool std::operator !=<_Ty,_Ty>(const std::allocator<_Ty> &,const std::allocator<_Ty> &) throw()' 
1>   with 
1>   [ 
1>    _Ty=Test 
1>   ] 
1>   test.cpp(11): or  'bool operator !=<std::allocator<_Ty>>(const T &,const T &)' [found using argument-dependent lookup] 
1>   with 
1>   [ 
1>    _Ty=Test, 
1>    T=std::allocator<Test> 
1>   ] 
1>   while trying to match the argument list '(std::allocator<_Ty>, std::allocator<_Ty>)' 
1>   with 
1>   [ 
1>    _Ty=Test 
1>   ] 
1>   C:\apps\MVS10\VC\include\vector(606) : while compiling class template member function 'void std::vector<_Ty>::_Assign_rv(std::vector<_Ty> &&)' 
1>   with 
1>   [ 
1>    _Ty=Test 
1>   ] 

... vector(609)は、この行に解決されます:

私は上記のコードをコンパイルする場合ですが、それがこのエラーで失敗し

#include <vector> 

//namespace XXX { 
    struct Test 
    { 
    bool operator==(const Test& r) const { return true; } 
    }; 
//} 
//typedef XXX::Test Test; 

template <typename T> inline bool operator!=(const T& l,const T& r) 
{ return !(l==r); } 

int main() 
{ 
    std::vector<Test> vt; 
    std::vector<Test> vt2 = std::move(vt); 
    return 0; 
} 

 else if (get_allocator() != _Right.get_allocator()) 

OTOH、私がnamespace XXX関連の行のコメントを外すと、苦情なしでコンパイルされます。

これはコンパイラのバグだと思っていますが、私はいくつかの独立した検証を探しています。

編集:ちょうど説明のために、VS2010で古いコードを初めて再コンパイルするとこの状況に遭遇しました。グローバルオペレーターは何年も前から廃止されていた(今削除された)。なぜコードが失敗したのか、他のコードが失敗したのか理解できませんでした。上のコードは、失敗したケースの私の蒸留です(明らかに、古いコードはstd::move()への呼び出しを含んでいません)。

UPDATE: -私はMSにバグを記録し、彼らは、これは「コンパイラの次のリリースでは、」固定されていると回答私は推測のVisual C++ 11を参照してください意味:http://connect.microsoft.com/VisualStudio/feedback/details/731692/regression-involving-global-operator-and-std-vector

+0

これを別のコンパイラで試しましたか? –

+0

@GregHewgill:私はGCCで再現できません。 – mcmcc

+0

@GregHewgill:前のコメントに嘘をつきましたが、私はC++ 11をサポートする便利な別のコンパイラを持っていないので、答えは「いいえ」です。 – mcmcc

答えて

10

をそれはバグです。

にはすべてoperator!=を指定しましたが、このような演算子が既に定義されている型と競合する可能性があります。 operator!=が使用することを検索しようとしたとき、あなたのライブラリの実装内部operator!=std::allocator<Test> 2の間のSへの呼び出しの解決時に

引数依存の照合は、[1]はTestの名前空間が検索可能にする(だけでなく、std[2]

ので:あなたの壊れた場合に

  • 、その名前空間にもマッチするoperator!=を含むグローバル名前空間です。今、これは問題ではありません。なぜなら、ネームスペースstdの関数がより良い一致であるからです。[3]; VSの不具合は、あいまいさが代わりに発生するということです。

  • しかしTest代わりに(typedefにもかかわらず)名前空間XXXであるとき、名前空間は上記ルールによる検索ではなくoperator!=ための競合の定義が含まれていない名前空間XXXです。

ベストはどのような場合には、これまでそのようすべてのタイプの演算子を定義していません。


[1]あなたのコンパイラ/ライブラリIMPLであなたのラインstd::vector<Test> vt2 = std::move(vt);のための実装のいくつかの部分がbool operator!=<std::allocator<Test>>(const std::allocator<Test>&, const std::allocator<Test>&)を呼び出している

[2] 引用は次のとおり

[C++11: 3.4.2/1]:When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function declarations (11.3) not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument).

[C++11: 3.4.2/2]:For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes is determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way:

  • [..]
  • If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces of which its associated classes are members. Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces of which any template template arguments are members; and the classes of which any member templates used as template template arguments are members. [ Note: Non-type template arguments do not contribute to the set of associated namespaces. —end note ]
  • [..]

[3] 引用は次のとおり

[C++11: 13.3.3/1]: Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i , ICSi(F1) is not a worse conversion sequence than ICSi(F2) , and then:

  • [..]
  • F1 and F2 are function template specializations, and the function template for F1 is more specialized than the template for F2 according to the partial ordering rules described in 14.5.6.2.

[C++11: 14.5.6.2/2]: Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. The deduction process determines whether one of the templates is more specialized than the other. If so, the more specialized template is the one chosen by the partial ordering process.

マイ解釈は、このプロセスはstd関数」であると判断することですグローバルネームスペースのものよりも「より専門的」であるため、実際にはあいまいではありません。このキックのお尻の答えにあなたの貴重な貢献のための


おかげ@BoPerssonとDavidRodrí[email protected]

+0

エラーは、 'Test 'に特化したグローバル'!= 'はADLのために見つかったと言います。疑わしいのは、行606にグローバル名前空間のオペランドがどのように含まれているかということです。 –

+0

@KerrekSB:はい、意味があります。それは前述の「葛藤」の一つです。 –

+0

私は、この同じエラーの他のバリエーションを考え出すために、typedefs、演算子のオーバーロード、namespace ...、std :: rel_opsなどのすべての組み合わせを試してみました。これが私がそれを(この特別な方法で)失敗させる唯一の方法です。どこかにコンパイラのバグがないと信じています。 – mcmcc

関連する問題