Very cool idea! Tried to allow the interface to be implemented implicitly: type Interface = object obj: pointer vtable: MethodTable MethodTable = object foo: proc(this: pointer): int proc toInterface[T](t: var T): Interface = let this = addr t let table {.global.} = MethodTable( foo: proc (this:pointer):int = cast[ptr T](this).foo ) result = Interface(obj: this, vtable: table) proc foo(this: Interface): int = this.vtable.foo(this.obj) type A = object B = object proc foo(a: ptr A): int = 3 proc foo(a: ptr B): int = 5 var a = A() b = B() a_i = toInterface(a) b_i = toInterface(b) c = @[a_i, b_i] for e in c: echo e.foo()
Works with two caveats: If toInterface is a converter and you try to use it implicitly nim generates illegal c code. And if toInterface is defined after exactly one implementation of foo() it breaks with > type mismatch: got (ptr A) but expected one of: proc foo(this: Interface): int If toInterface is a converter nim just straight up hangs up. If toInterface comes first or at least two foo()'s are defined before it everything works fine.