On Wednesday, 23 September 2020 at 19:16:13 UTC, H. S. Teoh wrote:

Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-)

What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null). But that's not what the OP is asking for in this case.


T

This has prompted me to write a data structure that I thought would be impossible until now. It's a data structure with a Start node with a link to next, then any number of Middle nodes with previous and next links, and an End node with a previous link all inheriting from a common interface Node. This is of course possible using runtime polymorphism, but I wanted it available for static dispatch rather than everything being listed as "Node" static type. The implementation is below and works.

Interestingly when I wrote it down with a pen and paper I thought that it would lead to infinitely recursive unwriteable data type and so didn't even bother trying to implement it. But D actually forms the correct static type, it prints the gobbledygook type I expect at compile time but the actual static type at runtime. Amazing! I have been using structs with tuples because I thought this data structure was impossible!

```
import std.stdio: writeln;

interface Node{}
class Start: Node
{
  Node next;
}
class Middle: Node
{
  Node prev;
  Node next;
}
class End: Node
{
  Node prev;
}

auto makeChain(Args...)(Args args)
if(Args.length > 3)
{
  args[0].next = args[1];
  static foreach(i; 1..(Args.length - 1))
  {
    args[i].prev = args[i - 1];
    args[i].next = args[i + 1];
  }
  args[$ - 1].prev = args[$ - 2];
  return args[0];
}

void main()
{
static const x = makeChain(new Start(), new Middle(), new Middle(), new Middle(), new Middle(), new End());
  pragma(msg, "x.next: ", x.next, "\n");
  writeln("x.next: ", x.next);
}
```

output:

```
x.next: Middle(Start(Middle(<recursion>)), Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), End(Middle(Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), End(<recursion>)))))))

x.next: node.Middle
```

Reply via email to