2

File A.hpp:

struct foo
{
   int x;
} foo;

inline bool operator ==(const foo &lhs, const foo &rhs)
{
   /* ... */
}

File B.hpp

#include "A.hpp"

namespace SomeNamespace
{
   bool operator==(const foo &lhs, const foo &rhs)
   {
      /* ... */
   }

   /* ... */
   void someFunction(const foo &foo_instance1, const foo &foo_instance2)
   {
      CPPUNIT_ASSERT(foo_instance1 == foo_instance2);
   }
}

The compiler error for the line with the ASSERT is:

error: ambiguous overload for 'operator==' ...

So, the problem is that the compiler sees both comparison operators.

The definition in the global namespace of A.hpp and the definition in the SomeNamespace of B.hpp are ambiguous.

Why does the compiler not use the defintion in the SomeNamespace?

Juergen
  • 3,489
  • 6
  • 35
  • 59

2 Answers2

2

You've defined the same function twice; what do you expect to happen? The compiler finds SomeNamespace::operator== with unqualified name lookup, and ::operator== with ADL. Since both have exactly the same signature, there is no way for the compiler to choose one over the other.

As a general rule, overloaded operators for a type should be defined in the same namespace as the type, and no where else. (If the overloaded operator takes two different types, defined in two different namespaces, I'd put the operator in the global namespace. But such cases are rare.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • I didn't know ADL also looks in global scope (if that's what you mean?). – jrok Sep 12 '13 at 12:40
  • @JamesKanze Can you explain the difference, please: [with struct](http://ideone.com/sSNBeR) and [with namespace](http://ideone.com/SsGflZ)? – lapk Sep 12 '13 at 13:07
  • Ok, is see that ADL is the actual "problem" since foo and its == operator are defined in the same(global) namespace. So this definition is considered as also the definition in the "local" namespace. Thx – Juergen Sep 12 '13 at 13:19
  • @PetrBudnik The difference in what? – James Kanze Sep 12 '13 at 13:26
  • @jrok ADL looks in namespaces implied by the arguments; in this case, it looks in the global namespace because that's where `foo` was defined. – James Kanze Sep 12 '13 at 13:27
  • @JamesKanze Well, sorry - it was two links actually if you click on them... But I have more clean version: http://ideone.com/FLg8h1 Why this is no problem then? – lapk Sep 12 '13 at 13:27
  • @PetrBudnik I still don't understand your question. In the code in the link, you're calling a function with `nullptr`, so ADL doesn't come into it. ADL adds namespaces determined by the arguments. – James Kanze Sep 12 '13 at 13:30
  • @JamesKanze Oh, I see! I guess, I had misunderstanding about ADL. Thanks, I appreciate you helping to sort it out. – lapk Sep 12 '13 at 13:34
2

In your program operator== is defined in Global namespace and Somenamespace.

So when you are trying to access the operator== then compiler is unable to resolve which function to call, as both functions have same signature ans both are visible to compiler.

So to use operator== defined in SomeNamespace you must use SomeNamespace::operator== and for the operator define in Global namespace you must use ::operator==.

shofee
  • 2,079
  • 13
  • 30
  • What are the lookup rules? I thought that the operator== in SomeNamespace is considered first since it should be found first.Isn't it that the compiler searches for names in a bottom-up-like manner(of the namespaces) and stops when the first correct definition is found? – Juergen Sep 12 '13 at 12:54
  • its not about top-to-bottom or bottom-up. When you are compiling the code compiler has both the functions visible "at same time". – shofee Sep 12 '13 at 12:59
  • @shobi Can you explain the difference, please: [with struct](http://ideone.com/sSNBeR) and [with namespace](http://ideone.com/SsGflZ)? – lapk Sep 12 '13 at 13:06
  • 1
    @Juergen pls refer this http://stackoverflow.com/questions/7374588/list-of-c-name-resolution-and-overloading-rules – shofee Sep 12 '13 at 13:08
  • @PetrBudnik sorry i didnt get u. – shofee Sep 12 '13 at 13:09
  • @shobi Click on the links to see the code in my previous comment, please. – lapk Sep 12 '13 at 13:11
  • @PetrBudnik by default member functions of struts are public, so compiler see's defination of do_it function twice(in case of struts), and when u wrap that function in namespace do_it goes in different scope one in namespace so and other in namespace so::other. – shofee Sep 12 '13 at 13:15
  • @shobi I think you misunderstood me... What do you say about this simple version then: http://ideone.com/FLg8h1 – lapk Sep 12 '13 at 13:26
  • @shobi Nothing wrong with it, but according to you it should not compile. – lapk Sep 12 '13 at 13:29
  • @PetrBudnik, you are misinterpreting me, according to me it will compile. – shofee Sep 12 '13 at 13:31
  • @shobi You are right, my mistake. I guess, I didn't fully understand ADL. Thanks, I appreciate your input. – lapk Sep 12 '13 at 13:33