使用约束实现From/Into for struct

yon*_*ong 3 traits rust

既然.max()不适用于f64s,我正在编写一个ForceOrd断言该参数不是a的结构NaN.预期用途如下:

let m = xs.iter().map(|&x| ForceOrd(x)).max().unwrap().into();
Run Code Online (Sandbox Code Playgroud)

但是,我无法Into使用错误编译特征实现:

conflicting implementations of trait `std::convert::Into<_>` for type `ForceOrd<_>`
Run Code Online (Sandbox Code Playgroud)

代码(游乐场):

#[derive(PartialEq, PartialOrd)]
pub struct ForceOrd<X: PartialEq + PartialOrd>(pub X);
impl<X: PartialEq + PartialOrd> Eq for ForceOrd<X> { }
impl<X: PartialEq + PartialOrd> Ord for ForceOrd<X> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.0.partial_cmp(&other.0).unwrap()
    }
}
/// doesn't work
impl<X: PartialEq + PartialOrd> Into<X> for ForceOrd<X> {
    fn into(x: Self) -> X { x.0 }
}
/// doesn't work either
impl<X: PartialEq + PartialOrd> From<ForceOrd<X>> for X {
    fn from(x: ForceOrd<X>) -> Self { x.0 }
}
Run Code Online (Sandbox Code Playgroud)

lje*_*drz 5

你不能同时拥有FromInto实现单一类型,即impl From<ForceOrd<X>> for X如果你也不能impl Into<X> for ForceOrd<X>.你也只需要一个.作为文档IntoFrom两者的状态:

From<T> for U implies Into<U> for T
Run Code Online (Sandbox Code Playgroud)

你可能应该只使用一个From实现.您可以看到以下问题以获取一般选择的信息:我应该何时实现std :: convert :: From vs std :: convert :: Into?

编辑:因为实现From不是(在这种情况下)只是删除impl Into,下面你可以看到如何实现这一点f64:

#[derive(PartialEq, PartialOrd, Debug)]
pub struct ForceOrd<X: PartialEq + PartialOrd>(pub X);

impl<X: PartialEq + PartialOrd> Eq for ForceOrd<X> { }

impl<X: PartialEq + PartialOrd> Ord for ForceOrd<X> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.0.partial_cmp(&other.0).unwrap()
    }
}

impl<X: PartialEq + PartialOrd> From<X> for ForceOrd<X> {
    fn from(x: X) -> ForceOrd<X> {
        ForceOrd(x)
    }
}

fn main() {
    let xs = vec![1.1f64, 3.5, 2.2];

    let max = xs.iter().map(|&f| <ForceOrd<f64>>::from(f)).max().unwrap();

    println!("{:?}", max); // prints "ForceOrd(3.5)"
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我担心这是你能得到的; 你将无法实现:

impl<X: PartialEq + PartialOrd> From<ForceOrd<X>> for X
Run Code Online (Sandbox Code Playgroud)

能够做决赛

<f64>::from(xs.iter().map(|&f| <ForceOrd<f64>>::from(f)).max().unwrap())
Run Code Online (Sandbox Code Playgroud)

因为f64这个箱子不是本地的.您可以在Niko Matsakis的这篇非常详细的博客文章中阅读有关此限制的更多信息,并在StackOverflow中查看此问题.