Sign in to follow this  
dcosborn

mem_fun with inheritance

Recommended Posts

I'm trying to convert a void ()(void) member function for a derived class to a functor which takes a base class pointer as its parameter. I figured this should be possible since the derived member function is really void ()(Derived *). I'm expecting it to be convertable to a functor of void ()(Base *), following the usual implicit upcast rules. However, the compiler is giving me an invalid conversion from Base* to Derived*. I'm assuming this downcast is the result of some sort of mem_fun template magic.
#include <iostream>
#include <tr1/functional>

struct A
{
	typedef std::tr1::function<void (A *)> F;

	explicit A(const F &f) : f(f) {}

	void Do()
	{
		f(this);
	}

	private:
	F f;
};

struct B : A
{
	B() : A(std::mem_fun(&B::MyF)) {}

	private:
	void MyF()
	{
		std::cout << "check" << std::endl;
	}
};

int main()
{
	B().Do();
	return 0;
}

Any ideas how I can make this work?

Share this post


Link to post
Share on other sites
Quote:
Original post by dcosborn
I figured this should be possible since the derived member function is really void ()(Derived *). I'm expecting it to be convertable to a functor of void ()(Base *), following the usual implicit upcast rules.


Wrong, the subtyping lattice is reversed for function arguments. That is, a function that accepts Derived* does not accept all Base* arguments (what about Base objects that are not Derived?). Your conversion is simply incorrect.

Share this post


Link to post
Share on other sites
Yeah, I see what you mean. It should be possible with a static_cast though right? Something like this?
static_cast<std::mem_fun_t<void, A> &>(std::mem_fun(&B::MyF))
I found a much cleaner solution: use a pure virtual F and derive it. Pretty obvious, but I was coding this at 4am so, you know... [rolleyes]

Share this post


Link to post
Share on other sites
Quote:
Original post by dcosborn
Yeah, I see what you mean. It should be possible with a static_cast though right? Something like this?


No, it will never be possible. Your cast can be mathematically proven to be incorrect. You can get around the compiler's common sense warnings with a reinterpret_cast, but don't expect to get any kind of correct behaviour out of it.


Share this post


Link to post
Share on other sites
Also, to be pedantic, the types for the member functions are void(Derived::*)() (and similarly for Base), not void()(Derived*) - the latter is not a type, although void(*)(Derived) would be a free function accepting a Derived object by value :) (I'd like to justify that by saying that it'd be important when searching for help, but it seems that Google ignores punctuation :( )

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this