I want the compiler to inline this, hard.
That's not going to happen.
You're using runtime polymorphism. By definition, the compiler cannot know which function will be called at call time. You are going to pay for virtual dispatch, whether you do it manually or let the compiler do it.
The absolute most inlining you will get is in the calls to the member functions. It still has to do a conditional branch based on a memory access (fetching the "type") to get to the "inline" part. And every new "state" you add will add another condition to that branch. At best, this will become a state table... which is no different from just a virtual function pointer: it fetches from a memory address, and uses that to branch to a particular piece of code.
Just like a vtable pointer, only you wasted your time implementing something the compiler could do for you.
I strongly advise you to profile this instead of simply assuming that your hand-written method can beat the compiler.
If you've decided to abandon language-level polymorphism, then you should use a boost.variant
and appropriate visitors instead. Your code would look like this:
typedef boost::variant<A, B> Wrapper;
struct FooVisitor : public boost::static_visitor<>
{
template <typename T> void operator()(T &t) {t.foo()};
};
You will have to make a FooVisitor
for every function you want to call. To call it, you do this:
Wrapper a = existingA;
boost::apply_visitor(FooVisitor(), a);
Obviously, you can wrap that in a simple function:
void CallFoo(Wrapper &a) {boost::apply_visitor(FooVisitor(), a);}
Indeed, you can make a whole template family of these:
template<typename Visitor>
void Call(Wrapper &a) {boost::apply_visitor(Visitor(), a);}
Note that parameter passing is not allowed (you have to store the parameters in the visitor itself), but they can have return values (you have to put the return type in the boost::static_visitor<Typename_Here>
declaration of your visitor).
Also note that boost::variant
objects have value semantics, so copies will copy the internal object. You can also use the boost::get()
syntax to get the actual type, but I would not suggest it unless you really need it. Just use visitors.