The C ++ code fragment owes its brevity to the convenient operator [] , which automatically creates a default value if it is not on the map. While Rust does not do this by default, itβs simple enough to say that this is done, as shown in Shepmaster's answer.
To avoid using entry(key).or_insert_with(ValueType::new) , you can add a method equivalent to C ++ operator [] in Rust HashMap . In the end, Rust has the necessary tools β it supports adding methods to existing types using attributes and has a trait roughly equivalent to the default C ++ constructor.
C ++ expressions:
map[0][0] = 0; map[0][1] = 1;
will be written as the following Rust, using a method that returns a link instead of operator [] :
*map.ensure(0).ensure(0) = 0; *map.ensure(0).ensure(1) = 1;
ensure will be declared in the attribute that must be imported by the code that the method wants to receive:
use std::collections::HashMap; use std::hash::Hash; trait MapDefault<K, V: Default> { fn ensure(&mut self, key: K) -> &mut V; }
... and is defined as follows:
impl<K: Eq + Hash, V: Default> MapDefault<K, V> for HashMap<K, V> { fn ensure(&mut self, key: K) -> &mut V { self.entry(key).or_insert_with(V::default) } }
It would be nice to define IndexMut for HashMap , which would reduce the expression to *map[0][0] = 0 , which is almost similar to the original C ++, but, unfortunately, Rust does not allow implementing operators for types from other modules.
user4815162342
source share