C++ 这是一个VC++;2010编译器错误?
使用Visual Studio 2010 SP1:C++ 这是一个VC++;2010编译器错误?,c++,visual-studio-2010,visual-c++,c++11,visual-c++-2010,C++,Visual Studio 2010,Visual C++,C++11,Visual C++ 2010,使用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&
#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;
}
OTOH,如果我取消注释与名称空间XXX
相关的行,它将毫无怨言地编译
我不得不认为这是一个编译器错误,但我正在寻找一些独立的验证
编辑:作为解释,我第一次用VS2010重新编译一些旧代码时遇到了这种情况。这家全球运营商是几年前(现在已被移除)的一些废物。我就是不明白为什么有些代码失败了,而有些代码没有。上面的代码是我对失败案例的提炼(显然,旧代码不会包含对std::move()
)的调用)
<强> Update:我用MS记录了一个bug,他们回答说,这是固定的,“在编译器的下一个版本中”——我假设这意味着Visual C++ 11。请参阅:
这是一个bug 您已决定提供操作员=
适用于所有类型,这显然会导致与已定义此类运算符的类型发生冲突
解析调用运算符期间的参数相关查找=在库实现[1]中的两个std::分配器之间的code>允许在尝试查找运算符时搜索Test
的命名空间(以及std
)=代码>使用[2]
因此:
- 在您的例子中,该名称空间是全局名称空间,它还包含一个
操作符=代码>匹配的。现在,这不重要了,因为命名空间std
中的函数更匹配[3]VS错误是产生了歧义。
- 但是当
Test
改为位于命名空间XXX
中时(尽管typedef
),根据上述规则搜索的命名空间改为命名空间XXX
,其中不包含与运算符冲突的定义=代码>
无论如何,最好不要为所有类型定义运算符
[1] 行的部分实现std::vector vt2=std::move(vt)编译器/库impl上的code>正在调用bool操作符=(const std::allocator&,const std::allocator&)
[2] 引文如下:
[C++11:3.4.2/1]:
当函数调用(5.2.2)中的后缀表达式是非限定id时,可以搜索通常非限定查找(3.4.1)过程中未考虑的其他命名空间,并且在这些命名空间中,可以找到不可见的命名空间范围友元函数声明(11.3)这些对搜索的修改
取决于参数的类型(对于模板参数,模板参数的名称空间)
[C++11:3.4.2/2]:
对于函数调用中的每个参数类型T
,都有一组零个或多个关联的名称空间和一组零个或多个关联的类名称空间和类的集合完全由函数参数的类型决定(以及任何模板参数的名称空间)。Typedef名称和用于指定类型的使用声明不属于此集合名称空间和类的集合按以下方式确定:
- [……]
- 如果
T
是类类型(包括联合),则其关联类为:类本身;其所属类别(如有);以及它的直接和间接基类。其关联的名称空间是其关联的类所属的名称空间。此外,如果T
是类模板专门化,则其关联的命名空间和类还包括:与为模板类型参数提供的模板参数类型关联的命名空间和类(不包括模板参数);任何模板参数都是其成员的名称空间;以及任何用作模板参数的成员模板都是其成员的类。[注意:非类型模板参数不构成相关名称空间集。-结束注意]
- [……]
[3] 引文如下:
[C++11:13.3.3/1]:
根据这些定义,一个可行函数F1
被定义为比另一个可行函数F2
更好的函数,如果对于所有参数i
,ICSi(F1)
不是比ICSi(F2)
更差的转换顺序,然后:
- [……]
F1
和F2
是功能模板的专门化,根据14.5.6.2中描述的偏序规则,F1
的功能模板比F2
的模板更专业化
[C++11:14.5.6.2/2]:
偏序通过依次转换每个模板(见下一段)并使用函数类型执行模板参数推断,选择两个函数模板中哪一个更专业。演绎过程确定一个模板是否比另一个模板更专业。如果是这样,则偏序过程会选择更专业的模板
我的解释是,这个过程决定了std
中的函数比全局名称空间中的函数“更专业”,因此实际上不应该存在歧义
感谢@BoPersson和@DavidRodríguez对这个问题的回答做出的宝贵贡献。你用其他编译器尝试过吗?@GregHewgill:我不能用GCC复制。@GregHewgill:我在前面的评论中撒了谎,我手头没有支持C++11的编译器,答案是否定的。@LightnessRacesinOrbit:关于什么?@LightnessRacesinOrb
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> ]
else if (get_allocator() != _Right.get_allocator())