izex
izex

Reputation: 123

Befriending a class

I am trying to befriend a class in order for it to be able to reach a private constructor of it.

In some_file.h

class B;    

namespace some_name {
class A {
  public:
    A() {}
  private:
    A (int x) {}
    friend class ::B;
};
}

In other_file.h

#include "some_file"

namespace {
class B {
  protected:
    A* get_a(int x) { return new A(x); }
};   
}

When compiling this code, I get - error: 'some_name::A::A(int)' is private.

I now, it is private, this is why I befriended B. What am I doing wrong here? Can't you befriend your constructor? Is there a namespace issue?

Thanks

Upvotes: 1

Views: 494

Answers (4)

ereOn
ereOn

Reputation: 55736

Doing this:

namespace {
class B {
  protected:
    A* get_a(int x) { return new A(x) };
}   
}

You're not putting B in the root (global) namespace but in an anonymous one.

So B can't be reached by ::B.

If you want B to be in the root (global) namespace, just don't enclose it with namespace at all. This should do the trick.

Upvotes: 9

Puppy
Puppy

Reputation: 146930

You only forward declared and friended a class B in the global namespace. Not a class B in a namespace whatever. You need to fully qualify the name of B.

Edit: Thanks ereOn.
I made a slight mistake. It's true that the reason that you've got a problem is because you've mis-declared and mis-referred-to B, but my original statement wasn't quite true. You need to take B out of the anonymous namespace - it's pointless being in a header anyway.

Upvotes: 1

Chubsdad
Chubsdad

Reputation: 25497

Can't you befriend your constructor?

You can as shown below

struct B{
    B();
    void f();
};

struct A{
    friend B::B();
private:
    A(){}
};

B::B(){A a;}       // fine

void B::f(){A a;}  // error

int main(){
}

Upvotes: 0

wilhelmtell
wilhelmtell

Reputation: 58677

The problem is that you refer to B as ::B instead of B. Meaning, you're telling the compiler that B is a global name, but in fact it isn't: it's inside an anonymous namespace. You don't have to remove the anonymous namespace, it's just that it may not do what you expect it to do. Because the anonymous namespace is in a header it means what's inside that namespace is linked statically to any implementation file that includes the header. That's not very useful, because you hide nothing. You might as well remove that anonymous namespace.

Upvotes: 0

Related Questions