Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between <T: Trait> Box<T> and &Trait / Box<Trait>?

When writing code with traits you can put the trait in a trait bound:

use std::fmt::Debug;

fn myfunction1<T: Debug>(v: Box<T>) {
    println!("{:?}", v);
}

fn myfunction2<T: Debug>(v: &T) {
    println!("{:?}", v);
}

fn main() {
    myfunction1(Box::new(5));
    myfunction2(&5);
}

Or directly in a Box or reference type:

use std::fmt::Debug;

fn myfunction3(v: Box<Debug>) {
    println!("{:?}", v);
}

fn myfunction4(v: &Debug) {
    println!("{:?}", v);
}

fn main() {
    myfunction3(Box::new(5));
    myfunction4(&5);
}

These give the same output. So what is the difference?

(This question was inspired by another question where this was just one of several intermingled concepts)

like image 523
Erik Vesteraas Avatar asked Jul 17 '17 19:07

Erik Vesteraas


People also ask

What is a trait object?

A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.

What is dynamic dispatch rust?

Dynamic dispatch. Rust provides dynamic dispatch through a feature called 'trait objects'. Trait objects, like &Foo or Box<Foo> , are normal values that store a value of any type that implements the given trait, where the precise type can only be known at runtime.

What is dyn rust?

dyn is a prefix of a trait object's type. The dyn keyword is used to highlight that calls to methods on the associated Trait are dynamically dispatched. To use the trait this way, it must be 'object safe'. Unlike generic parameters or impl Trait , the compiler does not know the concrete type that is being passed.


1 Answers

Importantly, you don't have to put the generic type behind a reference (like & or Box), you can accept it directly:

fn myfunction3<T: Debug>(v: T) {
    println!("{:?}", v);
}

fn main() {
    myfunction3(5);
}

This has the same benefits of monomorphization without the downside of additional memory allocation (Box) or needing to keep ownership of the value somewhere (&).

I would say that generics should often be the default choice — you only require a trait object when there is dynamic dispatch / heterogeneity.

like image 156
Shepmaster Avatar answered Sep 20 '22 13:09

Shepmaster