user2138149
user2138149

Reputation: 16841

C++ How to write a friend function binary operator which lives in a namespace in a separate compilation unit

I can't seem to figure out how to get the following to compile.

I am trying to write a binary operator which:

Here's some code:

// header.h

namespace ns1
{
    namespace ns2
    {

        class myClass
        {

            friend bool operator==(const myClass& l, const myClass& r);

        protected:

            int a;
        };

    }
}
// header.cpp

#include "header.h"

using namespace ns1;
using namespace ns1::ns2;

bool operator==(const myClass& l, const myClass& r)
{
    if(l.a != r.a) return false;
    return true;
}
// main.cpp

#include "header.h"

using namespace ns1::ns2;
using namespace std;

int main()
{
    myClass class1;
    myClass class2;

    if(class1 == class2)
    {
        cout << "hello world" << endl;
    }

    return 0;
}

This is the output from the compiler:

In function ‘bool operator==(const ns1::ns2::myClass&, const ns1::ns2::myClass&)’:
error: ‘int ns1::ns2::myClass::a’ is protected within this context

I have a suspicion that this is related to the compiler not understanding which namespace operator== should be in. I have tried explicitly declaring this, but that didn't help either.

The question is what is going on here? What is the compiler thinking?

Edit

Note: I posted this edit in response to an answer which was then deleted. The suggestion was to put the operator inside ns1::ns2, however this did not work. See the below output.

New compiler output:

error: ‘bool ns1::ns2::operator==(const ns1::ns2::myClass&, const ns1::ns2::myClass&)’ has not been declared within ‘ns1::ns2’ [-Werror]
bool ns1::ns2::operator==(const myClass& l, const myClass& r)

note: only here as a ‘friend’
friend bool operator==(const myClass& l, const myClass& r);

Upvotes: 0

Views: 167

Answers (1)

Nimrod
Nimrod

Reputation: 3543

The problem here is when you declare a friend function inside your class, this function belongs to the innermost enclosing namespace, you have to define

bool ns1::ns2::operator==(const myClass& l, const myClass& r)

It should be defined inside namespace ns1::ns2 but not just introduced it with using directives,

// header.cpp

#include "header.h"

namespace ns1 {
    namespace ns2 {
        bool operator==(const myClass& l, const myClass& r)
        {
            if(l.a != r.a) return false;
            return true;
        }
    }
}

Demo

or

// header.h
namespace ns1
{
    namespace ns2
    {

        class myClass
        {
             ...
        };

        bool operator==(const myClass& l, const myClass& r);
    }
}


// header.cpp
bool ns1::ns2::operator==(const myClass& l, const myClass& r)

Demo


Another way is to declare your friend function as a global one,

// header.h
#pragma once
namespace ns1
{
    namespace ns2
    {
        class myClass;
    }
}

bool operator==(const ns1::ns2::myClass& l, const ns1::ns2::myClass& r);

namespace ns1
{
    namespace ns2
    {

        class myClass
        {

            friend bool ::operator==(const myClass& l, const myClass& r);

        protected:

            int a;
        };

    }
}

// header.cpp

#include "header.h"

using namespace ns1::ns2;
bool operator==(const myClass& l, const myClass& r)
{
    if(l.a != r.a) return false;
    return true;
}

Demo

Upvotes: 1

Related Questions