Kira Yamato wrote:
Suppose class B is a subtype of class A, i.e.,
class B : public A
{
...
};
Then, in C++, a pointer to type B can be treated as a pointer to type
A. So, I can do the following:
B *b;
A *a = b;
This morphism of types is what makes C++ so powerful.
But now how do I do the following kind of morphism? Suppose I have
functions
void foo(const B &);
and
void bar(const A &);
I like to be able to declare a function pointer
void (*fp)(const B&);
and make "polymorphic" assignments like
p = foo; // this is ok in C++.
p = bar; // semantically this make sense, but C++ syntax won't
allow this!
Yes.
I know the last line of code is not valid C++ because the function
signatures are required to be the same. However, on a semantic level,
I should be allowed to substitute calls to foo with calls to bar. This
is what I mean:
B b;
foo(b); // I can substitute the function foo in this line to
bar(b); // the function bar in this line.
So, at least on a semantic level I should be able to declare a
"polymorphic" function pointer that can points to both foo and bar
types.
void (*fp)(const B&) = bar;
fp(b); // here, b is passed as type A to fp since bar accepts
type A argument.
But I can't, because C++ doesn't work this way.
Right. You are using pointer to functions which are low level and have
limited semantics vs what you want. You should instead use something like
boost::function<> where you specify the signature of the function as per
valid call not to match identically with the called function (that is, as
long as the called function returned argument is convertible to your
specified returned type for boost::function and as long as the input
arguments are convertible from your specified ones to the ones the function
actually takes then it compiles).
This is basically some template machinery (you store the original function
pointer as a type independent of the type you are suposed to call but when
calling the proper conversions happen).
Now, I know the mantra "When in Rome, do as Romans." So, if this is
not a feature of C++, then I should rework a solution that is in C++.
But I'm just curious if anyone has a "good hack" to simulate this type
of polymorphism in C++?
No need for a hack, but a nice C++ compile time typesafe solution, something
like boost::function. Here example of what you want:
#include <iostream>
#include <typeinfo>
#include <boost/function.hpp>
struct A {};
struct B: A {};
bool func(A const& arg)
{
std::cout << "called: " << typeid(arg).name() << std::endl;
}
int main()
{
boost::function<int (B const&)> f = func;
f(B());
}
indeed do compile-time type-checking, then this is some cool stuff.
Can't wait to dig into boost to see how it's done.
Thanks.