Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining a custom equality operator in an anonymous namespace

Tags:

c++

c++17

I have a C-struct (in a C header file) that looks like so:

struct Foo {
  int a;
  int b;
  int c;
};
typedef struct Foo Foo;

I want to test equality of two vectors of these structs, and so I would like to define a custom equality operator for this struct for just my translation unit.

I am able to do so with

static inline bool operator==(const Foo&, const Foo&) {...}

but not with

namespace {
    bool operator==(const Foo&, const Foo&) {...}
}

Why can the equality template for std::vector not find this operator, and is there a better way than tossing a static inline in the global namespace?

like image 312
Mark Pauley Avatar asked Jan 27 '23 13:01

Mark Pauley


2 Answers

I think you'll find that std::vector actually does find the operator in the anonymous namespace, if that operator's declaration occurs before #include <vector>.

The reason it doesn't find it in your code is related to the two-phase lookup for names in template functions. The first phase finds candidates in all namespaces in scope. The second phase only finds dependent names. "Argument-dependent lookup" which searches the namespace containing the type is dependent just as the phrase says. Lookup in the anonymous namespace is not dependent, so it won't be done during the second phase.

See also:

  • Declare function after template defined
  • Template specialization doesn't see a function in its point of instantiation
  • Why does the compiler find my function if is not yet declared?
like image 66
Ben Voigt Avatar answered Feb 16 '23 02:02

Ben Voigt


The first thing to be noted is that an anonymous namespace is not the same as no namespace.

namespace
{
    bool operator==(const Foo&, const Foo&) {...}
}

is really something like

namespace ANameUniqueToTheFile
{
    bool operator==(const Foo&, const Foo&) {...}
}

using ANameUniqueToTheFile;

with the downside that the language does not give you the ability to get the name of the namespace.

For that reason, the operator== function defined in the anonymous namespace is not found using ADL.


I can see why you would want to put the operator== function in a namespace. One possbile way to do that would be to #include the .h file that defines the struct inside a named namespace.

FooWrapper.h:

namespace MyApp
{
   #include "foo.h"

   // Declare the function.
   bool operator==(Foo const& lhs, Foo const& rhs);
}

FooWrapper.cpp

#include "FooWrapper.h"

namespace MyApp
{
   // Implement the function.
   bool operator==(Foo const& lhs, Foo const& rhs) { ... }
}

However...

I realize that I'm simplifying a bit about what's in "foo.h". Adding all of them in namesapce MyApp might not be appropriate, specially if "foo.h" includes other .h files and/or standard header files. I am hoping it gives you some ideas on how to tackle the problem.

If putting all of "foo.h" in namespace MyApp does not work smoothly, it will probably be expedient to define the operato== function in global scope.

like image 33
R Sahu Avatar answered Feb 16 '23 02:02

R Sahu