Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 这是一个VC++;2010编译器错误?_C++_Visual Studio 2010_Visual C++_C++11_Visual C++ 2010 - Fatal编程技术网

C++ 这是一个VC++;2010编译器错误?

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&

使用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;
}
OTOH,如果我取消注释与
名称空间XXX
相关的行,它将毫无怨言地编译

我不得不认为这是一个编译器错误,但我正在寻找一些独立的验证

编辑:作为解释,我第一次用VS2010重新编译一些旧代码时遇到了这种情况。这家全球运营商是几年前(现在已被移除)的一些废物。我就是不明白为什么有些代码失败了,而有些代码没有。上面的代码是我对失败案例的提炼(显然,旧代码不会包含对
std::move()
)的调用)

<强> Update:我用MS记录了一个bug,他们回答说,这是固定的,“在编译器的下一个版本中”——我假设这意味着Visual C++ 11。请参阅:

这是一个bug

您已决定提供
操作员=
适用于所有类型,这显然会导致与已定义此类运算符的类型发生冲突

解析调用
运算符期间的参数相关查找=std::分配器之间的code>允许在尝试查找
运算符时搜索
Test
的命名空间(以及
std
)=使用[2]

因此:

  • 在您的例子中,该名称空间是全局名称空间,它还包含一个
    操作符=匹配的。现在,这不重要了,因为命名空间
    std
    中的函数更匹配[3]VS错误是产生了歧义。

  • 但是当
    Test
    改为位于命名空间
    XXX
    中时(尽管
    typedef
    ),根据上述规则搜索的命名空间改为命名空间
    XXX
    ,其中不包含与
    运算符冲突的定义=

无论如何,最好不要为所有类型定义运算符


[1] 行的部分实现
std::vector vt2=std::move(vt)正在调用
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())