Reputation: 4484
So I want to write a function like this:
fn is_longer_than<T>(thing: T, threshold: int) -> bool {
thing.len() > threshold
}
I'm pretty new to rust and static typing / generics in general, but from what I understand you need to constrain T
with a trait that, in this case, implements the method len
I tried to do something like this:
trait HasLength {
fn len(&self) -> int
}
fn is_longer_than<T>(thing: HasLength, threshold: int) -> bool {
thing.len() > threshold
}
But that doesn't work. What am I missing? I'm guessing there is a pre-defined trait that covers this case? Even so, is there a way to define it anyways (for the sake of learning)
Upvotes: 2
Views: 1000
Reputation: 13667
You do need to constrain T
to the trait HasLength
, this is done with the syntax like <T: HasLength>
.
trait HasLength {
fn len(&self) -> int;
}
fn is_longer_than<T: HasLength>(thing: T, threshold: int) -> bool {
thing.len() > threshold
}
This declares that the function is_longer_than
takes any type T
that has an implementation of HasLength
. Note that you will have to define an implementation (with impl
) for every type you may want to pass to is_longer_than
.
Alternatively, the function could be defined as:
fn is_longer_than2(thing: &HasLength, threshold: int) -> bool {
thing.len() > threshold
}
This declares a function that takes a trait object, which will include both a reference to the data and one to a dynamic dispatch table for the trait. You will still have to define the appropriate impl
in order to create the trait object.
The difference between the two forms is that the first form will be specialized for every type, that is, a different version of the function will be compiled for every type that is used with the function. The second form will be more like OO-code in language like Java - only a single version of the function will be compiled, but this version will have to use the dynamic dispatch table to call len
.
Here is an example impl
for the HasLength trait, that defines the length of an i32
as the number of base-10 digits needed to represent it:
impl HasLength for i32 {
fn len(&self) -> int { self.to_string().len() as int }
}
Upvotes: 4