What you want is covariant argument types. This is not supported in C++, because it breaks type safety. To better understand this, let's take a simple example:
struct Vehicle {};
struct Tricycle : Vehicle {};
struct Tank : Vehicle {};
void drive(Vehicle const & b) { ... }
void giveToChild(Tricycle const & b) { ... }
Here we have a simple type hierarchy, as well as two functions taking a reference to respectively the base class and one of the derived class. Now, if what you ask for were allowed, we could do the following:
typedef void (*funcPtr)(Vehicle const &);
funcPtr = &giveToChild; // this is not allowed
funcPtr(Tank()); // oops, I just gave a tank to my child!
The language could implement some sort of runtime type verification, but this is not how C++ works.
However, the reverse conversion (contravariance) could be allowed without any issues (actually, C# delegates allow it), but is not possible in C++ for some reasons I am not aware of. Here is a sample of what it would allow:
typedef void (*funcPtr)(Tricycle const &);
funcPtr = &drive; // this could be allowed, but is not (in C++)
funcPtr(Tricycle()); // I can only drive a tricycle, but that's ok since it's a
// vehicle and I know how to drive all vehicles
So basically, what you are trying to achieve is not possible without resorting to forwarding functions that would check the type of the arguments before calling the original functions:
void forwardFN(Foo * f)
{
FooN * instance = dynamic_cast<FooN *>(f);
if (instance) fN(instance);
else throw type_exception();
}
dynamic_cast
you then you have to not shoehorn different function types into the same container. Separate these types in your design. – Tamathatamaulipas