Bug Vanquisher

8 June 2007

Reflection on Reflection: Function.Invoke/MemberFunction.Invoke

Filed under: C++ — Tanveer Badar @ 4:44 PM

Consider a language with no namespaces, no generic coding paradigms, just class hierarchy support. And for that matter consider no multiple inheritance to simplify things. To complicate things, functions can be overloaded but runtime polymorphosim is forbidden. Now, let your thoughts run free to the idea that all type information compiler found at compile time is also available at runtime through a special function GetType( ) on every class. This returns a Type object which you can query for all functions and call Invoke for a particular method on that object.

With this background, lets converse a bit about calling the functions. All you have available is the name of function to call and the meta data about the type. This function must perform these steps, in order.

  1. Validate its arguments.
  2. If it called on MemberFunction, search through the inheritance hierarchy for the function. Stop this procedure as soon as at least one matching function is found, otherwise, search only in the global scope.
  3. If no function was found in the last step, throw a notfoundexception.
  4. For all the functions in the found set, check their number of parameters and reject all those whose parameters are less than given.
  5. If no functions are left, throw an argumentmismatchexception.
  6. For the remaining functions, reject all candidates which take more parameters and do not have default values for extra parameters.
  7. If no functions are left, throw an argumentmismatchexception. By this time, we only have those functions left whose number of arguments are same or more with default values.

  8. Perform overload resolution among the candidates.
    1. Consider one function at a time. Perform positional type coercion for each parameter. Prefer implicit conversions and promotions as to user defined conversion. Also, user defined conversions must be discovered through meta data which will incur a performance hit everytime. Record the number of conversions required. Also perform coercion on return type. If return type can not be converted, reject that function.

    2. Those functions which require the minimum number of conversions are the best candidates.
  9. If no functions are left, throw an argumentmismatchexception.
  10. If we are left with more than one function, through an ambiguousmatchexception.
  11. If the function can not be accessed by the caller, throw an uncallableexception.
  12. Perform type coercion on parameters for the candidate function.
  13. Perform type coercion on return value of the candidate function and return it to caller.

If we allowed more generality than what was excluded, the conditions would have been much worse.

  1. With namespace, there is single global scope. You must have a Type object for each namespace. Overloads can be found at any level of namespace hierarchy too.

  2. With generic code, there is no way to instantiate a new class each time you specify parameters for which a concrete instantiation does not exist. Therefore, an additional check must be done to see that arguments match the type of object that are called on. Also, those arguments which participate in generic type deduction cannot have type coercion applied to them. A generic type argument inferable through multiple parameters must be same for every individual inference.

  3. You want multiple inheritance, only more work for Invoke. It has to search all branches of base classes simultaneously. If the function was declared in multiple base classes, it should throw an ambiguous match exception. Therefore, it must construct a tree rooted at the type of calling object and traverse it depth first to find the candidates and perform overload resolution among them.

  4. If someone thought virtual functions are a must, then, how are you going to invoke the most derived implementation when all you have is only a pointer to the function implementation at most till this level of inheritance. They must be invoked through the exact reference to the calling object and no other way.

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: