Fortunately I was not able to reproduce the dynamic field lookup with Std.instance and the cpp target using
recent Haxe/hxcpp development versions. This already cuts down most of the performance penalty...
::B tmp = ::Std_obj::instance(a,hx::ClassOf< ::B >());
tmp->foo();
While you should probably file an issue on Haxe questioning the different behavior of casting + type checking
on the cpp target, I advise you not to dismiss the benefits of the Std.instance overhead,if you
haven't yet established it as the bottleneck.
As for some way to hide or automate the creation of a temporary variable in an unsafe cast, how about a function
like the following (adapted from Std.instance, if you're curious):
public static inline function unsafeCast<T:{},S:T>( value : T, c : Class<S> ) : S {
var ret:S = cast value;
return ret;
}
If inlined as so, it still generates an extra stack variable and assignment, but you can try to tune it more. Also,
it can easily be changed to something else if, for instance, the behavior of (cast a:B) in the cpp target changes.
::B tmp;
{
::B ret = a;
tmp = ret;
}
tmp->foo();
Coming back to Std.instance, you could make your unsafeCast function call it in debug mode.