简体   繁体   中英

Why overloaded operator== for std::weak_ptr instantiated with type defined in namespace can't be found?

I'm using Visual Studio 2015.

Any idea why this code compiles:

#include <memory>

class Foo;
class Bar;
typedef std::pair<Foo*,std::weak_ptr<Bar>> Object;
typedef std::vector<Object> ObjectVect;

bool operator==( std::weak_ptr<Bar> left,
                 std::weak_ptr<Bar> right )
{
    return left.lock() == right.lock();
}

int main( int argc, char* argv[] )
{
    ObjectVect vect;
    Object obj;
    auto foundIter = std::find( vect.begin(), vect.end(), obj );
    return 0;
}

while this one gives me error:

#include <memory>

class Foo;
namespace MyNamespace
{
    class Bar;
}
typedef std::pair<Foo*,std::weak_ptr<MyNamespace::Bar>> Object;
typedef std::vector<Object> ObjectVect;

bool operator==( std::weak_ptr<MyNamespace::Bar> left,
                 std::weak_ptr<MyNamespace::Bar> right )
{
    return left.lock() == right.lock();
}

int main( int argc, char* argv[] )
{
    ObjectVect vect;
    Object obj;
    auto foundIter = std::find( vect.begin(), vect.end(), obj );
    return 0;
}

Error C2678 binary '==': no operator found which takes a left-hand operand of type 'const std::weak_ptr' (or there is no acceptable conversion) test_cppunit_interpreter_base_multi_output c:\\program files (x86)\\microsoft visual studio 14.0\\vc\\include\\utility 216

Looks like it failes to find the comparator when Bar is located in a namespace...

Am I doing something wrong? Or could this be a compiler bug?

You should move operator== into the namespace to make ADL take effect; ADL will also examine the types used as the template arguments (ie MyNamespace::Bar ) and add the associated namespaces (ie MyNamespace ) to the set of name lookup. ie

namespace MyNamespace
{
    class Bar;
    bool operator==( std::weak_ptr<Bar> left,
                     std::weak_ptr<Bar> right )
    {
        return left.lock() == right.lock();
    }

}

Why the 1st case works fine?

Because ADL works for global namespace too. For the 1st case both Bar and operator== is defined in the same namespace (ie the global namespace).

Why the 2nd case doesn't work?

Firstly note that std::find is defined in the namespace std , and there're many operator== s defined in it (with different parameter types). Then according to the rule of unqualified name lookup , when operator== is found at the namespace std , the name lookup stops. That means without the help of ADL, the operator== defined in the global namespace won't be found at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM