Preserving const? -- A potential solution

Daniel Keep daniel.keep.lists at gmail.com
Sun Mar 8 03:12:31 PDT 2009



Tim M wrote:
> Firstly option 2 was just crazy and I don't know why you said that.

Because it's how .NET does it.  Granted, .NET doesn't really have
templates; just deferred type erasure.  Still, it's basically the same idea.

.NET has it a lot easier since its binaries include considerable
reflection information, plus the standard library has a
platform-independent assembler.

> For
> option 1 you identifying the limitations and are just trying to apply as
> many problems as you can though the main barriers can easily be lowered.

That's how I think: it's easy to come up with simple cases where a
design works.  The trick is to come up with a design that works even for
the complex cases.

> As you already know templates are a compile time feature, so that
> statement about the compiler needs to every possible call doesn't make
> that much sense, the template inference works only for compile time type
> recognition and that is all that my sample code I posted used:
>
> ...
> 
> This code when run will print: B- A.max()
> 
> It is still a "B" but compiler can only see the "A.(T)max(T,T)" being
> called. What can actually be computed by the compiler is that another
> member function with the same exact signature exists in one or more
> subclasses. With this knowledge it can compile the "max" template as it
> did with "A" for all it's subclasses and insert the runtime type
> checking to decide which of them to call.

It's somewhat hypocritical to say "the compiler [needing to know] every
possible call doesn't make that much sense" and then require the
compiler know of every possible subclass of a given class.  It's the
same issue, dressed in different clothes and a fake beard.

Avoiding dynamic instantiation, you HAVE to know what template instances
are going to be needed at compile time.  You can't wave your hands and
make it go away.

> So just to help clarify the template is not instantiated in different
> ways but the same instantiation is done for each compatible class function.
> 
> The example currently compiles in:
> 
> A.max(invariant int)()
> 
> I am suggesting to compile in:
> 
> A.max(invariant int)()
> B.max(invariant int)()
> //any other subclasses
> 
> + runtime type checking

OK: an instance has a pointer to its vtable.  Virtual method resolution
works by assigning each method an offset in this table at compile time.
 When called, the method's slot is found and the method's address is
read out.

So in order to have virtual templated members, you have to stuff the
instantiations into the vtable, or something like the vtable, somewhere.

Let's take your example: the compiler knows all subclasses.  This
requires all-at-once compiling to be mandated by the language; any given
file will depend not only on the modules it directly references, but all
modules that subclass any classes it references.  It also means you
cannot ever have classes subclassed by an external library, since these
will be unavailable at compile time.

You still need to find a vtable for these methods.  Since you don't want
to know all function calls, we can't extend the existing vtable because
otherwise we can't predict the order in which extra entries will show up.

So let's add a new hidden field for each instance that points to a
hashtable of methods, indexed by mangled template name, for that class.
 The compiler then generates a static ctor that fills in the hashtable
at program startup.  Calling a virtual template member now requires a
hashtable lookup, plus another 4 bytes for every object instance.

Knowing every function invocation isn't much better: the one advantage
of that method is that the vtable can be fixed, so we don't need the
hashtable any more.

But in either case, I don't think the tradeoff is anywhere near worth it.

The only solution that I think would be acceptable would be the second I
mentioned; and that's obviously a tremendous amount of work.

But I could be wrong.  It could be that there's a really easy way of
implementing this.  That said, I have no idea what it is, and I've never
seen anyone suggest anything feasible.

  -- Daniel



More information about the Digitalmars-d mailing list