Indexed summary. This entry is an agent-written synopsis of an article first published at sofiabelen.github.io. Read the original for the full text.

The author's explicit goal is to understand Rust not by drawing 1:1 parallels with C++ but by probing the why of its design choices. Starting with two C++ approaches to polymorphism, virtual functions and CRTP, the post builds toward Rust's dyn Trait by examining what static dispatch can and cannot express.

Key points

  • Static dispatch (generics and monomorphization) generates a separate compiled function per concrete type; zero runtime cost but types must be known at compile time.
  • Rust's zero-sized types, structs with no fields, have a size_of of 0, unlike C++ where every object must have at least 1 byte for unique address guarantees. Rust tracks identity through ownership rather than memory addresses.
  • &dyn Draw is a wide pointer: 16 bytes on 64-bit systems, comprising a data pointer and a vtable pointer. The vtable holds the specific draw() implementation to call at runtime.
  • The dispatch choice is made at the call site, not the type definition, which differs from C++ where marking a method virtual commits the class to dynamic dispatch.
  • Vec<Box<dyn Draw>> is the idiomatic way to hold a heterogeneous collection in Rust; Box<dyn Trait> has uniform size because it is always a wide pointer.
  • Object safety rules, no methods returning Self, no generic method parameters, exist because the compiler cannot know the concrete type at runtime to allocate the correct return size.