In the below code, there are two \"equivalent\" calls to std::for_each
using boost:bind
expressions. The indicated line compiles, the indicated fai
The reason for this restriction is enforcement of access control across different classes that share a common base.
This is reinforced by notes in Core Language Defects Report defect #385, the relevant part copied here for reference:
[...] the reason we have this rule is that
C
's use of inherited protected members might be different from their use in a sibling class, sayD
. Thus members and friends ofC
can only useB::p
in a manner consistent withC
's usage, i.e., inC
or derived-from-C
objects.
As an example of something this rule prevents:
class B {
protected:
void p() { };
};
class C : public B {
public:
typedef void (B::*fn_t)();
fn_t get_p() {
return &B::p; // compilation error here, B::p is protected
}
};
class D : public B { };
int main() {
C c;
C::fn_t pbp = c.get_p();
B * pb = new D();
(pb->*pbp)();
}
The protected status of D::p
is something we want the compiler to enforce, but if the above compiled that would not be the case.
Actually, this seems logical. Inheritance gives you access to Derived::foo and not to Base::foo. Let me illustrate with a code example:
struct Derived : public Base
{
void callPrivateMethod(Base &b)
{
// this should obviously fail
b.foo(5);
// pointer-to-member call should also fail
void (Base::*pBaseFoo) (int) = &Base::foo; // the same error as yours here
(b.*pBaseFoo)(5);
}
};
It's all about "context". In the first call the context of the call is Derived
which has access to the protected members of Base
and hence is allowed to take addresses of them. In the second the context is "outside of" Derived
and hence outside of Base
so the protected member access is not allowed.