Reputation: 31
Halp! Im a rust newbie and ive battled through a bunch of stuff over the last few days but cannot find any information about this. I have a generic struct (which i have simplified down to illustrate the issue). I want to be able to create a struct that does a bunch of stuff with a std::collections::HashMap , HashSet , List etc Im assuming i need to imply that T must implement a new method .. using a trait? or similar but searches just turn up basic stuff
public struct dude< T > {
data : std::sync::Arc< T >,
}
impl < T > dude< T > {
pub fn new() -> dude< T > {
Reloader{ data : Arc::new( <T>::new() ) }
}
}
Produces the following error:
<T>::new();
^^^ function or associated item not found in `T`
Upvotes: 3
Views: 2847
Reputation: 73450
When you use functions on a generic in rust, you need to specify a trait bound that proivdes those functions.
For example what if I tried to call Dude::new()
with a class that doesn't provide a new
function? In some languages (like C++) this would be flagged as an error where you tried to actually create the instance - but in rust, there is a principle of locality of reasoning.
There is an existing trait that provides functionality like new()
- Default
- which provides Default::default()
using that as a trait bound looks like this:
use std::sync::Arc;
pub struct Dude<T> {
data : std::sync::Arc<T>,
}
impl<T:Default> Dude<T> {
pub fn new() -> Dude<T> {
Dude{ data : Arc::new( Default::default() ) }
}
}
The Default trait is implemented already for many types, for any custom types you can easily derive it (and clippy even gives you a warning about not implementing it im many places).
Now I can write:
let dude: Dude<String> = Dude::new();
It probably makes sense implement this for Dude
too, rather than provide new inside Dude
itself.
impl<T:Default> Default for Dude<T> {
fn default() -> Dude<T> {
Dude{ data : Arc::new( Default::default() ) }
}
}
Upvotes: 7