You can write code blocks by enclosing them with triple backticks ```:
```rust
struct Holder {
...
```
giving:
struct Holder {
objects: Vec<Box<dyn Object>>,
}
impl Holder {
fn add_object<T : Object> (
self: &'_ mut Self,
object: T,
)
{
self.objects
.push(Box::new(object))
;
}
}
Now, regarding the issue at hand, Box<dyn Trait>
is just sugar for Box<dyn Trait + 'static>
, meaning that the trait object / type erased element has a : 'static
bound (meaning that it is not borrowing any local, and thus the value is guarantee not to dangle at any time, which makes it usable for as long as we wish. If we had, for instance, T = &'a str
, then we would be borrowing a str
ing for some lifetime 'a
, after which the str
ing could be freed, which would make using such reference / pointer unsound. So when 'a != 'static
, it would be unsound to say that such a pointer lives for 'static
, which is what dyn Trait + 'static
says.
You can solve this in two ways:
-
either you forbid such short-lived references (recommended for the sake of simplicity). That's what adding
T : 'static
as the compiler suggests does. When'a != 'static
, for instance, you will not be able to useT = &'a str
. -
or you decide that you do not need such a long-lived value; that borrowing for the lifetime
'a
is fine. You must then replace every occurence ofBox<dyn Trait + 'static>
(or the equivalentBox<dyn Trait>
) by aBox<dyn Trait + 'lifetime>
, by adding / infecting everything with a<'lifetime>
lifetime parameter. This way, you can loosen your function into taking aT : 'lifetime
for some generic'lifetime
, which will makelifetime
"become"'a
when usingT = &'a str
:
trait Object {}
struct Holder<'lifetime> {
objects: Vec<Box<dyn Object + 'lifetime>>,
}
impl<'lifetime> Holder<'lifetime> {
fn add_object<T : Object + 'lifetime> (
self: &'_ mut Self,
object: T,
)
{
self.objects
.push(Box::new(object))
;
}
}
-
Playground (compiles just fine).
-
(The first option is just the special case of this more general / generic code, whereby
'lifetime
is chosen equal to'static
). -
Note that infecting
Box<dyn Trait + ... >
with a'lifetime
parameter greatly reduces the benefits and thus point of using aBox
(owning pointer) for the indirection: at that point, using&'lifetime dyn Trait
(sugar for&'lifetime (dyn Trait + 'lifetime))
would not be that much less ergonomic, and would avoid needing toBox
things around (playground).