Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does implicit == on map<<int,MyClass> not compile?

I have a strange issue defining == for one of my class. I simplified the code here to an example that i tested on my visual 2013; MyClass is defined in namespace N

This does compile:

N::MyClass a, b;
bool test = a == b;

This too:

const N::MyClass a, b;
bool test = a == b;

This does not compile

std::map<int, N::MyClass> a, b;
bool test = a == b;

For your information the == operator is declared like this :

bool operator==(const N::MyClass & a, const N::MyClass & b);

here is the error I get : error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const MyClass' (or there is no acceptable conversion)

But from what I know the map operator is defined : map == reference on cppreference.com

could someone explain me why this is wrong ?

Thank you in advance.

I did not find an answer and I'm sorry if this is stupid.

[solution] If I mode the operator into the namespace it works :

bool N::operator==(const MyClass & a, const MyClass & b);

But I don't know why I need to do that, is it in the language definition ? (I guess yes)

like image 202
dzada Avatar asked Sep 01 '13 10:09

dzada


1 Answers

Based on your description, I guess your equality operator is not defined in the same namespace as your class. The following demonstrates the situation:

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

The obvious fix is to define the equality operator in the same namespace as the class. The reason it doesn't work is the two-phase name look-up in templates: when a templates is instantiated it only does second phase name look-up, i.e., it only finds functions relating to template arguments based on explicit qualification or argument dependent look-up. The equality operator isn't qualified in std::map<K, V> (well, it is never qualified when using operator notation to call it) and, thus, it needs to be found by argument dependent look-up.

like image 55
Dietmar Kühl Avatar answered Sep 25 '22 13:09

Dietmar Kühl