class scope virtual template functions

Chris Wright dhasenan at gmail.com
Thu May 29 16:59:10 PDT 2008


BCS wrote:
> Somewhere IIRC the spec says that classes can't have template methods 
> that operate as virtual functions. This is because it would quickly 
> become a nightmare trying to put together the v-table because only the 
> linker would really know how many different function are in it.

You also have to be sure to instantiate all overrides of the template. 
But these are manageable, even so. You can keep a list of instantiations 
for each template alongside the object file, plus a list of overrides. 
Then as a pre-linking step, you instantiate them all.

This would be a HUGE advantage. Want to support user-defined 
interceptors on whatever your library is doing? If your library does any 
nontrivial stuff at compiletime, you can't. Not without virtual templates.

> However in highly limited cases, this is not an issue.
> 1) the template members are enumerations (just build the whole set)
> 2) the function has no parameters (only one version can be built)
> 3) no general form of the template exists, only explicit specializations 
> (ditto enum)
> 4) class scope aliases of member templates are used. (instance the 
> template and stuff it in as a normal function)

You can just use a switch statement, but that gets unmaintainable before 
too long.

> There is also an interesting possibility suggested by #2: allow a 
> template with no args that is penalized for the actual type of the 
> specific object
> 
> Example:
> 
> class A
> {
>  char[] Name(this)()  // "this" is a pseudo arg
>  { return typeof(this).stringof; }
> }
> class B : A {}
> 
> writef("%s\n", (new A).Name); // outputs "A"
> writef("%s\n", (new B).Name); // outputs "B"
> 
> Thoughts?
> 
> I have some thoughts on how to use this functionality, but it's to 
> ill-formed at this time to fit in this margin.

Dconstructor needs this. My dependency injection library has the 
following basic API:

class Builder
{
	T get(T)();
}

The best way I've seen to allow user-defined interceptors is:
class Builder (TInterceptors...)
{
	// Actually working with this is quite a pain.
	private TInterceptors _interceptors;
	
	T get (T) ()
	{
		foreach (interceptor; _interceptors)
		{
			if (T t = interceptor.handle!(T)(this))
			{
				return t;
			}
		}
		// ...
	}
}

This isn't very good; you can't add or remove interceptors at runtime, 
and you need to add all the interceptors at the same place. Plus it's 
really ugly to work with a type tuple variable.

I'd rather an interface like:
interface IBuildInterceptor
{
	T handle(T)(IBuilder builder);
}

interface IBuilder
{
	T get(T)();
	void addInterceptor(IBuildInterceptor interceptor);
}

In .NET or Java, you wouldn't think twice about how to create such an 
interface. In D, you don't even think once; you know it's impossible.



More information about the Digitalmars-d mailing list