问题
I want to define methods for Untyped and Unit or basically every type, but I want to specialize a few methods just for Unit.
The problem is that Rust doesn't allow two implementations here. I am using Rust 1.9, do I need to enable specialzation or is this just not possible?
use num::Float; // 0.2.1
use std::marker::PhantomData;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Untyped;
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Unit;
struct Vector<T, Type> {
data: [T; 3],
_m: PhantomData<Type>,
}
impl<T> Vector<T, Unit>
where
T: Float,
{
fn length(&self) -> T {
println!("SPECIAL");
T::one()
}
}
impl<T, Type> Vector<T, Type>
where
T: Float,
{
fn length(&self) -> T {
println!("NON SPECIAL");
T::one()
}
}
fn main() {
let v = Vector::<f32, Untyped> {
data: [1., 2., 3.],
_m: PhantomData,
};
let v1 = Vector::<f32, Unit> {
data: [1., 2., 3.],
_m: PhantomData,
};
let l = v.length();
let l1 = v1.length();
}
error[E0592]: duplicate definitions with name `length`
--> src/main.rs:19:5
|
19 | / fn length(&self) -> T {
20 | | println!("SPECIAL");
21 | | T::one()
22 | | }
| |_____^ duplicate definitions for `length`
...
29 | / fn length(&self) -> T {
30 | | println!("NON SPECIAL");
31 | | T::one()
32 | | }
| |_____- other definition for `length`
回答1:
You are trying to specialize a method defined in an inherent impl, rather than specializing a method defined in a trait. This appears to not be supported at the moment, even after adding default to the "non special" length method. RFC 1210 mentions inherent impls as a possible extension, which I understand as not being considered for implementation at the moment.
As a workaround, consider moving your method to a trait. This requires specialization to be enabled to work, so you'll need to use a nightly compiler until the feature is stabilized.
Instead of defining the default implementation on the trait, we define it in the general impl. We need to add the default contextual keyword to that function.
#![feature(specialization)]
trait VectorExt<T>
where
T: Float,
{
fn length(&self) -> T;
}
impl<T, Type> VectorExt<T> for Vector<T, Type>
where
T: Float,
{
default fn length(&self) -> T {
println!("NON SPECIAL");
T::one()
}
}
impl<T> VectorExt<T> for Vector<T, Unit>
where
T: Float,
{
fn length(&self) -> T {
println!("SPECIAL");
T::one()
}
}
// This `impl` is not strictly necessary,
// but it will let users of your type
// use the `length` method
// without having to `use` the `VectorExt` trait.
impl<T, Type> Vector<T, Type>
where
T: Float,
{
fn length(&self) -> T
where
Self: VectorExt<T>,
{
VectorExt::<T>::length(self)
// can also be written as: <Self as VectorExt<T>>::length(self)
}
}
playground
来源:https://stackoverflow.com/questions/38024059/how-can-i-specialize-a-method-for-a-specific-generic-type