Any idea for a solution to handle overloads when dynamically implementing methods?

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Sep 11 11:23:09 PDT 2013


On Mon, Sep 09, 2013 at 10:16:42PM +0200, Gary Willoughby wrote:
> Just wondered if i could pick you brains for a nice solution to
> dynamically add methods to a class, paying particular attention to
> overloads. I'm currently writing a mocking framework and
> everything's coming along nicely and i'm wondering how to handle
> replacing overloads of the mocked class.
> 
> To create a new mocked class this is the code:
> 
> 	auto mock = new Mock!Person();
> 
> Simple enough, mock now contains an extended class with all the
> methods set to assert(false) because there are no implementations
> yet. What i need to do is to add the implementations dynamically.
> This is the code i propose.
> 
> 	mock.addMethod("getAge", int delegate(){
> 		return 40;
> 	});
> 
> 	assert(mock.getAge() == 40);
> 
> Which i guess would be easy to implement but it doesn't handle
> overloads because the method string doesn't contain enough
> information to define which overload it's implementing.
> 
> Any nice ideas what would be a nice way of supporting this? I
> thought i'd ask while i have a think and get some tea. :)

One idea I have is to use the built-in "typetuples" as a way of
disambiguating between different overloads. For example, something like
this:

	// This captures the function argument type list in a form that
	// we can call .mangleof on.
	template ArgTypesWrapper(ArgTypes...) { }

	// This builds a unique string to identify a specific overload
	// based on the function name and the .mangleof of its argument
	// types. The key to this trick is that the .mangleof of a
	// template encodes its argument types, so it is unique per
	// combination of argument types.
	template FuncSignature(string funcName, ArgTypes...) {
		enum FuncSignature = funcName ~ ArgTypesWrapper.mangleof;
	}

	class Mock(... /* whatever you currently have here */) {
		// This unfortunately has to be a template function in
		// order to be able to capture the argument types of the
		// delegate in the typetuple A. This may complicate the
		// implementation of how you'd actually dispatch to the
		// overload implementation at runtime.
		void addMethod(R, A...)(string funcName, R delegate(A...) dg)
		{
			string overloadName = FuncSignature!(funcName, A);

			// Now overloadName should be a unique string
			// representing that particular combination of
			// function name and argument types, i.e., it's
			// a function signature. So you can use it to
			// identify which overload is which.
		}
	}


T

-- 
Meat: euphemism for dead animal. -- Flora


More information about the Digitalmars-d-learn mailing list