2

In a function generic on T, how can I properly create and initialize a variable of type T in safe (or unsafe) Rust? T can be anything. What is the idiomatic way of doing such thing?

fn f<T>() {
    let t: T = todo!("what to put here?");
}

One possible use case might be to use T as a temporary variable for swapping.

11
  • 3
    If not Default, what would you want it to initialize to? Commented Feb 7, 2021 at 18:43
  • 2
    You already answered your own question. If you don't want to use unsafe code then you have to place a Default bound on T and initialize the generic type with T::default(). If you're willing to use unsafe code then you can look up the implementation for rotate_right within the Rust standard library, or just use rotate_right directly. Commented Feb 7, 2021 at 19:02
  • 1
    You're basically asking "How do I do X, other than the ways that the standard library and language permit me to do X?" Commented Feb 7, 2021 at 20:38
  • 1
    I voted to close because, having preemptively ruled out the answers you know of, you've left us with no real parameters for what kind of answer would be acceptable. rotate_right is in the standard library, and you can read the code for it -- it just uses unsafe (although admittedly not in exactly the way you refer to). What makes you think there needs to be another way? Or why do the two options you've ruled out not satisfy your requirements? Commented Feb 7, 2021 at 20:40
  • 1
    My point was not that you should use rotate_right necessarily, but that the question already contained two reasonable answers and seemed to be asking for "anything else?" without any real parameters on the solution. Since the edits the question no longer has this problem; I've revoked my close vote. Commented Feb 8, 2021 at 13:44

1 Answer 1

3

Putting a Default bound on T is the idiomatic way to construct generic types within a generic function.

There's nothing special about the Default trait though and you can declare a similar trait and use that within your generic functions.

Also, if a type implements Copy or Clone you can initialize as many copies and clones as you want from a single value.

Commented examples:

// use Default bound to call default() on generic type
fn func_default<T: Default>() -> T {
    T::default()
}

// note: there's nothing special about the Default trait
// you can implement your own trait identical to it
// and use it in the same way in generic functions
trait CustomTrait {
    fn create() -> Self;
}

impl CustomTrait for String {
    fn create() -> Self {
        String::from("I'm a custom initialized String")
    }
}

// use CustomTrait bound to call create() on generic type
fn custom_trait<T: CustomTrait>() -> T {
    T::create()
}

// can multiply copyable types
fn copyable<T: Copy>(t: T) -> (T, T) {
    (t, t)
}

// can also multiply cloneable types
fn cloneable<T: Clone>(t: T) -> (T, T) {
    (t.clone(), t)
}

playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.