auto ref

Bill Baxter wbaxter at gmail.com
Thu Dec 17 10:03:51 PST 2009


On Thu, Dec 17, 2009 at 9:28 AM, dsimcha <dsimcha at yahoo.com> wrote:
> == Quote from Nick Sabalausky (a at a.a)'s article
>> Pardon my ignorance, but why is it that templated functions can't be
>> virtual?
>
> This is an unfortunate consequence of compilation model leaking out into language
> design.  You're supposed to be able to subclass a base class even if you don't
> have the full source code to it.  Let's say we have:
>
> class A {
>    void doStuff(T)(T arg) {}
> }
>
> class B : A {
>    void doStuff(T)(T arg) {
>        writeln("In B.");
>    }
> }
>
> And then we do:
>
> B b = new B;
> b.doStuff(1);
>
> The instantiation of B.doStuff() with an int would require that the vtable for A
> be updated to include doStuff!(int).  This is not possible if we also allow base
> classes to be compiled separately from derived classes and the code that uses the
> derived class.
>
> The only solution I see would be to completely get rid of separate compilation.
> For my personal use, since most of my projects are under 10k lines and take a
> negligible amount of time to compile anyhow, I'd be in favor of this.  However,
> for larger projects or projects that require things to work based only on
> interface, without access to the full source code, this is probably impractical.

This 'auto ref' stuff and the multi-flavor 'vconst' functions are
basically templates with a known list of instantiations (ref /no-ref,
and const/immutable/plain)
In theory there's no reason you couldn't allow templates to also
create virtual functions, if you limit yourself to listing the
possible instantiations up front.

It feels like we may be missing out on a more general construct here
that could embrace all these cases via some extension to template
syntax.

I'm reminded of how Go interfaces do the job of both specifying that a
function is a template and checking constraints on use.

In D-ish syntax, Go uses something like this:
interface Foo { ... }
void doSomething(Foo f, int x) { ... }

To mean something like

template CheckIfIsFoo!(T) { ... }
void doSomething(T)(T f, int x) if (CheckIfIsFoo!(T)) { ... }

The advantage is that the compiler can offer better error messages
about what part of the check fails, and the syntax is cleaned up
significantly (less repetition, less proliferation of parentheses).

Maybe a similar approach could be used to separate the specification
of these alternatives into pseudo-types that can then be used as
parameters.

Like
static interface VConst(T) {
   constnessOf(T) is in [const, immutable, !const];
}
VConst!(Bar) doSomething(VConst!(Bar) b, int y) {...}

static interface MaybeRef(T) {
   refnessOf(T) is in [ref, !ref];
}
MaybeRef!(Bar) doSomethingElse(MaybeRef!(Bar) b, int y) { ... }


Anyway, the more I look at standard C++ and D template syntax the more
I think that Go is onto something.  Yeh, there are some generic
container-like templated types where T really can be any type (which
Go inexcusably ignores), but very often there are some restrictions on
T that are important enough and common enough that they deserve some
support with a terse syntax.

--bb



More information about the Digitalmars-d mailing list