Michel Fortin wrote:
The thing is that the name of that "catchAllHandlerFunc" function needs to be standardised for it to work with runtime reflection.

I agree with this wholeheartedly.

However, opDotExp would be hamstringed if it were made to serve this function.

Since classes can implement interfaces, you could expose an interface IDispatch or the like. This doesn't suffice for structs, though.

Let's look at the swizzle case. You want a class or a struct with a function for every permutation of "xwyz". Beside doing that manually, here's what you can do:

Solution A: use a mixin. This will add 256 functions to your struct, and those functions will appear in the functionList used by invokeViaReflection.

Solution B.1: use a templated catch-all function, and use the name to instanciate the catch-all. Calling the function will work at compile time, but at runtime invokeViaReflection is left in the dust.

Solution B.2: in addition to the templated catch-all function in B.1, add a runtime catch-all. This is about twice the work, but invokeViaReflection can work with those functions.

The standard form will be something like:
class Dispatch : IDispatch
{
auto opDotExp(string name)(...) { return dispatch(name, _arguments, _argptr); }
   auto dispatch(string name, ...)
   {
      // do stuff
   }
}

This isn't much added work.

Now, let's look at the proxy case, where you want to forward function calls to another object. In fact, there are two variant of this case: one where you know the type at compile-time, one where you don't (you only know the base class) but still want to forward all calls.

Solution A: use a mixin. The mixin will create a wrapper function for all functions in the wrapped object it can find using compile-time reflection, and those functions will appear in the functionList used by invokeViaReflection.

That's a lot of work, but it can get you a performance increase in the case where you know something about the class at compile time (for instance, you have an object that implements a particular interface, but you want to call non-interface functions via the wrapper).

Of course, you could manually forward methods as well and get the same performance increase. But that would be more difficult to write.

Note that I'm not that much against a templated opDot, I just want to point out its drawbacks for reflection. I'm also unconvinced of its usefulness considering you can do the same things better using mixins leaving only the runtime case to be solved, where you are better served without a template anyway.

Well, you can do the same things with some other advantages with mixins, but it's harder to write.

I think the appropriate solution is to add a solver to the compiler that can determine valid inputs for opDotExp and, if that set is below a threshold, unroll the template into regular member functions.

Or, you know, just implement a static foreach that you can use in templates. And anything else that we can think of that's reasonable to make the mixin solution easier to work with.

If that's accomplished, there'd be no reason to have opDotExp as a template.

Reply via email to