Structures also can be generic. We use the generic parameter(s) inside at least one of the fields, and inside some of the methods.
16.5.1Defining a generic struct¶
Here is the definition of a Point structure for a cartesian point:
struct Point<T> {
x: T,
y: T,
}This Point structure may be generated for any type T.
Here we generate the Point structure for 32-bit signed integers:
let p = Point { x: 5, y: 10 };Now we generate the Point structure for 64-bit floats:
let p1 = Point { x: 1.0, y: 4.0 };The way we have defined the struct makes possible to use a string
type, or any other type:
let _p = Point { x: "abc", y: "def" };16.5.2Defining methods¶
When defining methods for a generic struct, the impl statement must list the generic parameters with their eventual constraints.
Here we define two methods x() and y() in order to retrieve the two
coordinates:
impl<T> Point<T> {
pub fn x(&self) -> &T {
&self.x
}
pub fn y(&self) -> &T {
&self.y
}
}And we use them to print the coordinates of point p:
println!("p=({},{})", p.x(), p.y());p=(5,10)
16.5.3Specialization¶
It is possible to implement a method only for one specialization of
a generic. In the following example, we specialize Point<T> for
f32, and define a method that computes the distance from origin
only for this specialization:
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}16.5.4Trait bound¶
If we restrict T to floating point types (f32 and f64) using the
num-traits library, we can define functions that use floating point
operations in general, whatever the float type. See
Bounding a generic method about trait
bounding for generic methods. For instance we can implement a
distance() method that computes the distance between the current
point and another. To do this we bound T to the trait Float. This
example requires the external num_traits crate, which is not
available in this notebook’s kernel, so it is shown but not executed:
use num_traits::Float;
impl<T: Float> Point<T> {
pub fn distance(&self, other: &Self) -> T {
let a = self.x - other.x;
let b = self.y - other.y;
(a * a + b * b).sqrt()
}
}Here is an example in which we compute the distance between two points
p1 and p2:
let p2 = Point { x: 6.5, y: 11.0 };
println!("Distance between p1 and p2: {}", p1.distance(&p2));