std::map — Maps and Dictionaries
std::map provides the standard associative container surfaces:
HashMap(K, V)— an unordered map backed by a hash table.TreeMap(K, V)— an ordered map backed by a red-black tree.
The API is specified here; it targets the compiler and will grow as the language gains first-class container ergonomics (in particular, more borrow- and move-aware iteration and accessors).
Considerations#
In the Supported forms:
HashMap(K, V)owns keys and values by value:clear/droprunDropfor all live entries,removedrops the removed key and returns the removed value,putreturns the previous value when replacing an existing entry.TreeMap(K, V)does not runDropfor stored keys/values yet; it should be treated as single-slot storage in the Supported forms.HashMap(K, V)stores keys and values in the compiler’s scalar-slot layout (sizeof(K)/sizeof(V)bytes, multiples of 8 in the current subset). This supports multi-slot value types such asstringand non-opaque structs/enums over supported primitives.TreeMap(K, V)is still limited by its current node layout and, for now, should be treated as single-slot storage (keys/values that lower to a singleu64slot).- These containers are intended for “plain” value types:
- primitive scalars,
stringviews,- and small POD structs over those primitives.
getanditerproduce values by value (copy element bytes). For value types that requireDrop, copying out creates duplicate ownership. Prefer move-out operations (removeand the returned previous value fromput) forDrop-managed values.
These limits are expected to be relaxed as the language gains borrow-aware accessors and iterators for container storage.
HashMap (HashMap(K, V))#
Construction#
HashMap requires hashing and equality functions (similar in spirit to the
Hash and KeyEqual customization points of C++ std::unordered_map). For
common key types, std::map ships default hash_* / eq_* helpers and
HashMap provides empty() / init(cap) overloads that select those defaults
implicitly.
For common key types, std::map provides default hash_* / eq_* helpers so
callers do not need to write hashing and equality functions themselves.
Default helper functions are provided for these key types:
bool- fixed-width integers (
u8/i8/u16/i16/u32/i32/u64/i64/u128/i128) - platform integers (
int,usize,size/isize) charstring(bytewise FNV-1a)
Example (using std::map defaults via HashMap.init(cap) / HashMap.empty()):
import std::map;
import std::result;
import std::memory;
type Map = std::map::HashMap(u64, int);
type InitResult = std::result::Result(Map, std::memory::AllocFailed);
fn main () -> int {
match (Map.init(16)) {
InitResult::Ok(map) => {
let mut m: Map = map;
let put_r = m.put(1, 10);
if put_r.is_err() { m.drop(); return 2; }
let v: int = m.get(1) ?? 0;
m.drop();
return v;
},
InitResult::Err(_) => {
return 1;
},
}
}
Example (custom hashing/equality):
import std::map;
import std::result;
import std::memory;
type Map = std::map::HashMap(u64, int);
type InitResult = std::result::Result(Map, std::memory::AllocFailed);
fn hash_u64 (k: u64) -> u64 { return k; }
fn eq_u64 (a: u64, b: u64) -> bool { return a == b; }
fn main () -> int {
match (Map.init_with(16, hash_u64, eq_u64)) {
InitResult::Ok(map) => {
let mut m: Map = map;
m.drop();
return 0;
},
InitResult::Err(_) => {
return 1;
},
}
}
HashMap.init_with(cap, ...) validates the requested capacity:
cap < 0returnsAllocErrorKind::InvalidInput.- very large
capvalues that would overflow internal sizing arithmetic returnAllocErrorKind::Overflow.
Core API#
HashMap(K, V) provides:
fn empty () -> HashMap(K, V);(only for default key types)fn init (cap: i64) -> std::result::Result(HashMap(K, V), std::memory::AllocFailed);(only for default key types)fn empty_with (hash: fn(K) -> u64, eq: fn(K, K) -> bool) -> HashMap(K, V);fn init_with (cap: i64, hash: fn(K) -> u64, eq: fn(K, K) -> bool) -> std::result::Result(HashMap(K, V), std::memory::AllocFailed);fn len (self: &HashMap(K, V)) -> i64;fn is_empty (self: &HashMap(K, V)) -> bool;fn capacity (self: &HashMap(K, V)) -> i64;fn contains_key (self: &HashMap(K, V), key: K) -> bool;fn get (self: &HashMap(K, V), key: K) -> V?;fn put (mut self: &HashMap(K, V), key: K, value: V) -> std::result::Result(V?, std::memory::OutOfMemory);Inserts or replaces and returns the previous value, if present.fn remove (mut self: &HashMap(K, V), key: K) -> V?;fn iter (self: &HashMap(K, V)) -> HashMapIter(K, V);fn clear (mut self: &HashMap(K, V)) -> void;fn reserve_additional (mut self: &HashMap(K, V), additional: i64) -> std::memory::OutOfMemory?;fn drop (mut self: &HashMap(K, V)) -> void;Releases the table backing memory.
Complexity expectations:
- average
O(1)forget/put/removewhen the hash distribution is good, - worst case
O(n)in adversarial collision patterns.
TreeMap (TreeMap(K, V))#
TreeMap is an ordered map. It requires an ordering function.
Core API#
TreeMap(K, V) provides:
fn init (cmp: fn(K, K) -> int) -> TreeMap(K, V);Contract:cmp(a, b) < 0iffa < b;cmp(a, b) == 0iff keys are equal.fn len (self: &TreeMap(K, V)) -> i64;fn is_empty (self: &TreeMap(K, V)) -> bool;fn contains_key (self: &TreeMap(K, V), key: K) -> bool;fn get (self: &TreeMap(K, V), key: K) -> V?;fn put (mut self: &TreeMap(K, V), key: K, value: V) -> std::result::Result(V?, std::memory::OutOfMemory);fn remove (mut self: &TreeMap(K, V), key: K) -> V?;fn iter (self: &TreeMap(K, V)) -> TreeMapIter(K, V);fn clear (mut self: &TreeMap(K, V)) -> void;fn drop (mut self: &TreeMap(K, V)) -> void;
Complexity expectations:
O(log n)lookup/insert/remove.
Iteration#
Both maps provide iteration through an iterator interface:
HashMapIter(K, V)implementsstd::interfaces::Iterator(Entry(K, V)).TreeMapIter(K, V)implementsstd::interfaces::Iterator(Entry(K, V)).
The produced item type is:
struct Entry(K, V) {
key: K,
value: V,
}
Notes:
- Iteration is by value (copies out
keyandvalue). HashMapiteration order is unspecified.TreeMapiteration yields entries in ascending key order (as defined bycmp).
std::interfaces surface#
The current std::map implementation already exposes its common container
shape through std::interfaces:
HashMap(K, V)implements:LenCapacityIsEmptyClearReserveAdditionalDropTreeMap(K, V)implements:LenIsEmptyClearDropHashMapIter(K, V)andTreeMapIter(K, V)implementstd::interfaces::Iterator(Entry(K, V)).
This is the intended stdlib style: even before dynamic interface dispatch exists, the core map types should read like canonical examples of the shared container protocols.
Design goals#
- Provide a consistent, ergonomic key→value container story in
std::without relying on a builtinmap(K, V)type form. - Make allocation behavior explicit and compatible with regions (
with) and--noheap. - Keep the API close in spirit to C++’s
std::unordered_mapandstd::map(operations, complexity expectations, and terminology), adapted to Silk.
Source repository · Edit this page · View Markdown