mem_fun with inheritance

Started by
3 comments, last by Zahlman 17 years, 6 months ago
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?
Advertisement
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.

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]
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.


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 :( )

This topic is closed to new replies.

Advertisement