I am trying to make convenient API where hashing algorithm parameter would be optional and default is used if none is specified. But I can not find good description on how default generic params work.
Most convenient would be function generic defaults, but as I understand it was axed: https://github.com/rust-lang/rust/issues/36887
I am a little bit surprised that I can declare struct with default generic param, but I can not create it without explicit specification of the param.
Here is what I have, but I can not figure out, how to make default type info flow from struct into impl:
mod scratch {
use failure::_core::marker::PhantomData;
trait Hasher {
fn hash(key: &[u8]) -> u32;
}
struct Murmur2 {}
struct Crc32 {}
impl Hasher for Murmur2 { fn hash(key: &[u8]) -> u32 {unimplemented!()} }
impl Hasher for Crc32 { fn hash(key: &[u8]) -> u32 {unimplemented!()} }
// I want murmur to be the default hasher
struct Producer<H: Hasher=Murmur2> {
phantom: std::marker::PhantomData<H>,
}
impl<H: Hasher> Producer<H> {
fn send(&mut self, data: &[u8]) {
let hash = H::hash(data);
}
}
// Usage
fn call_it() {
let producer = Producer {phantom: PhantomData};
// ^^^^^^^^ cannot infer type for type parameter `H` declared on the struct `Producer`
}
}
The default only has any influence on what happens if you are mentioning the type (e.g. in a struct field), not what happens when you're constructing it. Take a look at how HashMap does it. Their new function is defined like this:
Ah, I understand now that what escaped me is a "specialization" which impl Producer<Murmur2> {...} provides. Now I do not even need default generic at all
The default only has any influence on what happens if you are mentioning the type (e.g. in a struct field)
Thanks @alice, that was another missing bit of understanding.
I've ended up with this api, which is aesthetically pleasing