This is literally the same question as this C++ question, but in Rust.
Suppose I have a "sparse vector" type that stores filled entries in a map of some kind. Unfilled entries are some kind of default value, like 0.
use std::ops::{Index, IndexMut};
use std::collections::BTreeMap;
use num_traits::Float;
struct SparseVector<T: Float, const N: usize>(BTreeMap<usize, T>);
// Returning a ref is easy when a value is present.
impl<T: Float, const N: usize> IndexMut<usize> for SparseVector<T, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.entry(index).or_insert(T::zero())
}
}
// What to return when we hit the default?
impl<T: Float, const N: usize> Index<usize> for SparseVector<T, N> {
type Output = T;
fn index(&self, index: usize) -> &T {
match self.0.get(&index) {
Some(value) => t,
None => ???
}
}
}
To implement Index
on this type, I need to return a &T
. For filled entries, that's just a reference to the value. How do I return a ref to the default?
I obviously can't return a &0
for lifetime reasons.
I can't necessarily store the default in a const field of the struct impl. It might not come from a const function.
I'm trying to avoid storing the default value on every instance of the type. It's literally the same value, why must it be allocated on every instance, etc.
The C++ answer is to return an instance of a wrapper type that dereferences to a &T
. But in Rust, a Deref<Target = &T>
cannot be substituted for &T
, as far as I know.
How can I implement Index
(override the []
operator) on this type?