So I have a trait called "Widget" which is quite simple:
pub trait Widget<T> {
fn common(&self) -> &Common;
fn value(&self) -> &T;
fn value_mut(&mut self) -> &mut T;
}
Other than the custom struct Common
(defined elsewhere), it should be clear that the Widget trait simply specifies that an immutable or mutable reference can be returned using .value()
and .value_mut
functions, and this will be of the same type as the Widget itself (T
).
So, for example, I have a "NumberWidget", like this...
pub struct NumberWidget<T> {
common: Common,
value: T,
range: RangeInclusive<T>,
}
impl<T: Numeric> NumberWidget<T> {
pub fn new(
...etc.
...which is constrained by the trait bound Numeric
- it can only apply to primitive numbers.
I want NumberWidget
to satisfy the trait Widget
, of course. But I cannot simply write...
impl Widget for NumberWidget {
Because both Widget and NumberWidget need a generic argument.
So let's say I want to have integer and float versions of "NumberWidget". The only way I have so far which works and compiles is to implement both explicitly:
impl Widget<f64> for NumberWidget<f64> {
fn common(&self) -> &Common {
&self.common
}
fn value(&self) -> &f64 {
&self.value
}
fn value_mut(&mut self) -> &mut f64 {
&mut self.value
}
}
impl Widget<i64> for NumberWidget<i64> {
fn common(&self) -> &Common {
&self.common
}
fn value(&self) -> &i64 {
&self.value
}
fn value_mut(&mut self) -> &mut i64 {
&mut self.value
}
}
This is fine for just two variations, but it's already more duplication than I feel comfortable with. I guess I'm looking for something like:
impl Widget<T: Numeric> for NumberWidget<T>
But this is not valid:
trait takes 1 generic argument but 0 generic arguments were supplied
expected 1 generic argument
associated type bounds are unstable
see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
associated type bindings are not allowed here
associated type not allowed here
cannot find type `T` in this scope
.etc. etc.
Is there a way to construct instances such as NumberWidget<i64>
, NumberWidget<usize>
, NumberWidget<f32>
, etc. without having to implement impl NumberWidget<i64> for Widget<i64>
, etc. explicitly for every possible Numeric type?
You've merely placed the type parameter in the wrong place, you're looking for this:
impl<T: Numeric> Widget<T> for NumberWidget<T> {
// ^^^^^^^^^^^^ The type parameter goes on the impl block itself
fn common(&self) -> &Common {
&self.common
}
fn value(&self) -> &T {
&self.value
}
fn value_mut(&mut self) -> &mut T {
&mut self.value
}
}