NilocEidlogger
NilocEidlogger

Reputation: 31

Calling T::new() from inside generic struct in Rust

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

Answers (1)

Michael Anderson
Michael Anderson

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

Related Questions