I'd like to std::bind
to a member function from a private base class, made "public" with a using
-declaration in the derived class. Calling the function directly works, but it seems binding or using member function pointers doesn't compile:
#include <functional>
struct Base {
void foo() { }
};
struct Derived : private Base {
using Base::foo;
};
int main(int, char **)
{
Derived d;
// call member function directly:
// compiles fine
d.foo();
// call function object bound to member function:
// no matching function for call to object of type '__bind<void (Base::*)(), Derived &>'
std::bind(&Derived::foo, d)();
// call via pointer to member function:
// cannot cast 'Derived' to its private base class 'Base'
(d.*(&Derived::foo))();
return 0;
}
Looking at the error messages above, the issue seems to be that Derived::foo
is still just Base::foo
, and I can't access Base
through Derived
outside Derived
itself.
This seems inconsistent - should I not be able to use direct calls, bound functions, and function pointers interchangeably?
Is there a workaround that would let me bind to foo
on a Derived
object, preferably without changing Base
or Derived
(which are in a library I don't own)?
A private member of a class cannot be inherited and, as a result, is not available for the derivative class directly. What happens if private data is to be inherited by a derived class? C++ provides a third, protected, visibility modifier for restricted inheritance use.
Now, in Private inheritance, the public and protected members of the base class become private members of the derived class the private members of the base class cannot be accessed by the derived class.
the private members of the base class cannot be accessed by the derived class. the interface of the base class is not being inherited but its implementation is being inherited which means one can use the contents of the base class as it is using the member functions of the derived class. Let us consider a class for better understanding:
public, protected and private inheritance in C++ public, protected, and private inheritance have the following features: public inheritance makes public members of the base class public in the derived class, and the protected members of the base class remain protected in the derived class.
The issue here is what the using-declaration actually does:
struct Derived : private Base {
using Base::foo;
};
That brings Base::foo
into public scope in Derived
, but it doesn't create an entirely new function. It is not equivalent to having written:
struct Derived : private Base {
void foo() { Base::foo(); }
}
There is still only Base::foo()
. The using-declaration simply affects the access rules and the overload resolution rules. As such &Derived::foo
really has type void (Base::*)()
(and not void (Derived::*)()
!), since that is the only foo
that exists. Since Base
is private
, member access through a pointer to Base
is ill-formed. I agree that this is pretty unfortunate ("inconsistent" is a good word).
You can still create a function object that calls foo
. You just can't use the pointer to member. With C++14, this becomes straightforward if verbose (I'm assuming arbitrary arguments here and that void foo()
is merely a simplification of the problem):
auto d_foo = [d](auto&&... args){ return d.foo(std::forward<decltype(args)>(args)...); }
With C++11, you'd have to write a type with a variadic template operator()
.
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