Does A::foo
need to be declared public for B
to declare it friend?
class A {
protected: // public ?
void foo(int x);
};
class B : public A {
friend void A::foo(int); // not fine with GCC 4.8.1 but fine with VS 2013
void goo(int x) {foo(x);} // fine
static void hoo(int x) {}
};
void A::foo(int x) {B::hoo(x);} // friend declaration needed for this
Visual Studio 2013 thinks it is fine if A::foo is protected, but GCC 4.8.1 thinks it's not and wants it to be public. Which compiler is correct? My initial instinct was that it can be declared protected. After all, B is derived from A, so should have access to A::foo (as B::goo demonstrates trivially).
VS is correct here.
The name A::foo
is in fact accessible in the scope of B
since it's publicly derived from A
. To prove this, consider
class A {
protected:
void foo(int x);
};
class B : A {
using A::foo; // it's OK to refer to the name A::foo
};
void A::foo(int x) {}
So by using the quote § 11.3 [friend functions]
A name nominated by a friend declaration shall be accessible in the scope of the class containing the friend declaration.
we can argue that's there's no violation of the rules (foo
is also protected in the derived class).
It seems like in gcc, once the friend
keyword is placed in front of the friend function declaration, name lookup starts ignoring inheritance (nothing to do though with friendship not being inheritable)
As mentioned by 40two in the comments the same error is emitted from Clang and there's a bug report for it; this issue is also reffered to DR209. It seems that for the implementers to get this right is quite hard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With