Tbf this applies to Rust too. If the author writes
fn foo(bar: Box<dyn BarTrait>)
they have forced the caller into dynamic dispatch.Had they written
fn foo(bar: impl BarTrait)
the choice would've remained open to the callerTbf this applies to Rust too. If the author writes
fn foo(bar: Box<dyn BarTrait>)
they have forced the caller into dynamic dispatch.Had they written
fn foo(bar: impl BarTrait)
the choice would've remained open to the caller fn foo(bar: impl BarTrait)
and AFAIK it isn't possible to write that in C (though C++ does allow this kind of thing).Examples of type erasure in C++ are classes like std::function and std::any, and normally you need to implement the type erasure manually, but there are some library that can automate it to a degree, such as [1], but it's fairly clumsy.
[1] https://www.boost.org/doc/libs/latest/doc/html/boost_typeera...
This is monomorphized for every type you pass in, in short.
Not really. You can store it on any struct that specializes to the same type of the value you received. If you get a pre-built struct from somewhere and try to store it there, your code won't compile.
the struct in which it is stored, could be generic as well
No one would ask this question in the case where the struct is generic over a type parameter bounded by the trait, since such a design can only store a homogeneous collection of values of a single concrete type implementing the trait; the question doesn't even make sense in that situation.
The question only arises for a struct that must store a heterogeneous collection of values with different concrete types implementing the trait, in which case a trait object (dyn Trait) is required.