top | item 47158754

(no title)

gignico | 4 days ago

> Under the hood, a virtual table (vtable) is created for each class, and a pointer (vptr) to the vtable is added to each instance.

Coming from C++ I assumed this was the only way but Rust has an interesting approach where the single objects do not pay any cost because virtual dispatch is handled by fat pointers. So you carry around the `vptr` in fat pointers (`&dyn MyTrait`) only when needed, not in every instance.

discuss

order

cataphract|4 days ago

There have been type-erasure libraries in c++ for a longish time that allow choosing inline vtables and inline storage. It's definitely been a widely talked about technique for at least 10 years (I see talks about Dyno from 2017).

anon291|4 days ago

This is the standard type class approach. Haskell does the same thing.

menaerus|3 days ago

> only when needed

Do you know how is this exactly deduced?

dminik|3 days ago

It's not. The user has to decide.

A specific type/reference to a type will always use static dispatch.

fn foo(bar: &Baz) { bar.thing(); }

A dyn trait reference will always use dynamic dispatch and carry around the vtable pointer.

fn foo(bar: &dyn BazTrait) { bar.thing(); }

dalvrosa|4 days ago

Good point, thanks for sharing!