Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return boxed value?

I basically have a function that creates some object which need to be allocated on the heap. What I want to do is return from that function a structure containing a reference to that heap-allocated value.

struct Cont<'a> {
    pub v: &'a i32
}

impl<'a> Cont<'a> {
    fn new(v: &'a i32) -> Cont {
        Cont {
            v: v
        }
    }
}

fn f<'a>() -> Cont<'a> {
    let v = Box::new(6);

    Cont::new(&v)
}

fn main() {
    let c = f();

    println!("{}", c.v);
}

I'm getting error: 'v' does not live long enough.

You can find the example here.

like image 784
dragostis Avatar asked Mar 13 '23 07:03

dragostis


1 Answers

You cannot return a structure that only contains a borrowed pointer to your object, because your Box would be destroyed at the end of the function.

You need to transfer ownership of the Box out of the function so that the heap-allocated object remains alive. The simplest way to do this is to move the Box into your struct:

struct Cont {
    pub v: Box<i32>
}

impl Cont {
    fn new(v: Box<i32>) -> Cont {
        Cont {
            v: v
        }
    }
}

fn f() -> Cont {
    let v = Box::new(6);
    Cont::new(v)
}

fn main() {
    let c = f();

    println!("{}", c.v);
}

If you want a struct that is able to store either a borrowed pointer or an owning Box (or other kinds of smart pointers), we can make it generic over the Borrow trait.

use std::borrow::Borrow;

struct Cont<T> where T: Borrow<i32> {
    pub v: T
}

impl<T> Cont<T> where T: Borrow<i32> {
    fn new(v: T) -> Cont<T> {
        Cont {
            v: v
        }
    }
}

fn owned() -> Cont<Box<i32>> {
    let v = Box::new(6);
    Cont::new(v)
}

fn borrowed(v: &i32) -> Cont<&i32> {
    Cont::new(v)
}

fn main() {
    let c = owned();
    println!("{}", c.v);

    let x = 123;
    let c = borrowed(&x);
    println!("{}", c.v);
}
like image 55
Francis Gagné Avatar answered Mar 16 '23 01:03

Francis Gagné