为什么在地图<< int,MyClass>上隐式==不能编译?

dza*_*ada 5 c++ operators c++11

我有一个奇怪的问题,为我的一个班级定义==.我将这里的代码简化为我在visual 2013上测试的示例; MyClass在名称空间N中定义

这确实编译:

N::MyClass a, b;
bool test = a == b;
Run Code Online (Sandbox Code Playgroud)

这个也是:

const N::MyClass a, b;
bool test = a == b;
Run Code Online (Sandbox Code Playgroud)

这不编译

std::map<int, N::MyClass> a, b;
bool test = a == b;
Run Code Online (Sandbox Code Playgroud)

为了您的信息,==运算符声明如下:

bool operator==(const N::MyClass & a, const N::MyClass & b);
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误: error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const MyClass' (or there is no acceptable conversion)

但据我所知,地图运算符已定义:map == cppreference.com上的引用

谁能解释一下为什么这是错的?

先感谢您.

我没有找到答案,如果这是愚蠢的话,我很抱歉.

[解决方案] 如果我将运算符模式化为命名空间,它可以工作:

bool N::operator==(const MyClass & a, const MyClass & b);
Run Code Online (Sandbox Code Playgroud)

但我不知道为什么我需要这样做,是否在语言定义中? (我猜是)

Die*_*ühl 7

根据您的描述,我您的等式运算符没有在与您的类相同的命名空间中定义.以下说明了这种情况:

#include <map>

namespace foo
{
    class bar
    {
    };
}

using namespace foo;
bool operator== (bar const&, bar const&) { return true; }

int main()
{
    bar const b;
    b == b; // OK
    std::map<int, bar> mb;
    mb == mb; // ERROR
}
Run Code Online (Sandbox Code Playgroud)

显而易见的解决方法是在与类相同的命名空间中定义相等运算符.它不起作用的原因是模板中的两阶段名称查找:当模板被实例化时,它只进行第二阶段名称查找,即,它只根据显式限定或参数查找与模板参数相关的函数依赖查找.等式运算符没有限定std::map<K, V>(当使用运算符表示法调用它时,它永远不会被限定),因此需要通过参数相关的查找来找到它.

  • @dzada参见[最新标准草案](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3691.pdf),ADL部分3.4.2和第14.6节. 4用于不合格的从属名称的两阶段查找. (2认同)