rust pass box reference without move

雨燕双飞 提交于 2020-06-17 13:14:11

问题


Background:

I'm writing a RDBMS in rust

The db.catalog maintain a hashmap from table_id to table:

pub struct Catalog {
    table_id_table_map: HashMap<i32, Box<dyn Table>>,
}

And when I add a boxed table to the catalog, move occurred. Then I can't use table instance anymore:

// create table
let table = create_random_heap_table(....);
// add to catalog
db.get_catalog().add_table(Box::new(table), "heap table", "");
// access table instance
let table_id = table.get_id();

compile error:

error[E0382]: borrow of moved value: `table`
   --> src/lib.rs:113:32
    |
103 |                 let table = create_random_heap_table(
    |                     ----- move occurs because `table` has type `table::HeapTable`, which does not implement the `Copy` trait
...
111 |                 db.get_catalog().add_table(Box::new(table), "heap table", "");
    |                                                     ----- value moved here
112 | 
113 |                 let table_id = table.get_id();
    |                                ^^^^^ value borrowed here after move


回答1:


Once your Catalog takes ownership of the table, you can access it via reference.

If the use case you are describing is common, maybe you can adapt your add_table method to return a reference to the table which has just been added.

HashMap provides the Entry API as an ergonomic way to do this - for instance your add_table might look something like this:

fn add_table(&mut self, table: Box<dyn Table>/*, ... other arguments */) -> &mut Box<dyn Table> {

    let id = // figure out id somehow

    // Insert table into catalog and return a reference to it        
    self.table_id_table_map.entry(id).or_insert(table)
}

In that simplified example I am not considering what happens if the map already has an entry with the given id - there are similar patterns you can use to check for that if you logic requires it.

Now you can use it like this:

// create table
let table = create_random_heap_table(....);
// add to catalog
let table = db.get_catalog().add_table(Box::new(table), "heap table", "");
// access table instance
let table_id = table.get_id();


来源:https://stackoverflow.com/questions/62273711/rust-pass-box-reference-without-move

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!