Is this a compiler for VC ++ 2010?

Using Visual Studio 2010 SP1:

#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; } 

If I compile the code above as is, it fails with this error:

 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> ] 

... where vector(609) resolves this line:

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

OTOH, if I uncomment the lines associated with namespace XXX , it compiles without complaint.

I should think this is a compiler error, but I'm looking for some independent verification.

EDIT: Just as an explanation, I came across this situation when I first recompiled the old code with VS2010. Global operator a few years ago (now removed). I just could not understand why some code failed and others did not. The code above is my distillation of a failed event (obviously, the old code will not contain calls to std::move() ).

UPDATE: I registered a bug with MS and they replied that it was fixed "in the next version of the compiler" - I suppose it means Visual C ++ 11. See: http://connect.microsoft.com/VisualStudio/ feedback / details / 731692 / regression-involving-global-operator-and-std-vector

+6
source share
1 answer

This is mistake.

You decide to provide operator!= For all types that will obviously cause conflicts with types that already have such an operator.

Finding an argument-dependent argument while resolving an operator!= Call between two std::allocator<Test> inside your library implementation [1] allows you to search for the Test (and also std ) std when trying to find operator!= To use [2] .

So:

  • in your broken case, this namespace is a global namespace that also contains operator!= , which matches. Now it doesn’t matter, because a function in the std namespace matches better [3] ; VS error is that ambiguity arises instead.

  • but if Test instead in the XXX namespace (despite the typedef ), the namespace distorted by the rule above instead means the XXX namespace, which does not contain an inconsistent definition for operator!= .

It’s better not to define operators for all types ever similar, anyway.


[1] Some of the implementation of your string is std::vector<Test> vt2 = std::move(vt); in your compiler / library, impl calls the bool operator!=<std::allocator<Test>>(const std::allocator<Test>&, const std::allocator<Test>&) .

[2] Quotes follow:

[C++11: 3.4.2/1]: When the postfix expression in the function call (5.2.2) is unqualified-id, other namespaces can be found that are not taken into account in the ordinary unqualified search (3.4.1) < , and in these namespaces, declarations of the namespace name function (11.3) can be found that are not displayed elsewhere. These changes in the search depend on the types of arguments (and for template template arguments, template argument namespace).

[C++11: 3.4.2/2]: For each type of argument T in a function call, there is a set of zero or more related namespaces and a set of zero or more related classes to be considered . The sets of namespaces and classes are completely determined by the types of function arguments (and the namespaces of any template template argument). Typedef names and the declaration declarations used to indicate types do not contribute to this set. Sets of namespaces and classes are defined as follows:

  • [..]
  • If T is a class type (including unions), its associated classes: the class itself; the class of which he is a member, if any; and its direct and indirect base classes. Its associated namespaces are namespaces of which the associated classes are members. In addition, if T is a specialized specification of a class template, its associated namespaces and classes also include: namespaces and classes associated with template argument types provided for template type parameters (excluding template template parameters); namespaces whose members are template template arguments; and classes in which any member templates used as arguments to a template template are members. [Note. The non-piggy type template arguments do not contribute to the set of related namespaces. -end note]
  • [..]

[3] Quotes follow:

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

  • [..]
  • F1 and F2 are specialized function templates, and the function template for F1 more specialized than the template for F2 in accordance with the partial ordering rules described in 14.5.6.2.

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

My interpretation is that this process determines that a function from std is "more specialized" than a function in the global namespace, so there should not really be any ambiguity.


Thanks to @BoPersson and @ DavidRodríguez for your valuable contribution in responding to this blow.

+10
source

Source: https://habr.com/ru/post/910851/


All Articles