微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尽可能实施 Into,否则使用 TryInto

如何解决尽可能实施 Into,否则使用 TryInto

我有一个结构:

pub struct Point2D<T>(pub T,pub T);

我希望能够:

  • (A) 用 Point2D<T>(T,T) 变成 .into
  • (B) 如果 Point2D<A> 实现了 .tryInto,则将带有 (B,B)A 变成 TryInto<B>

我可以实施(A):

impl<T> std::convert::Into<(T,T)> for Point2D<T> {
    fn into(self) -> (T,T) {
        (self.0,self.1)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn into() {
        let a: Point2D<u32> = Point2D(42,42);
        let a_into :(u32,u32) = a.into();
        let b: (u32,u32) = (42,42);
        assert_eq!(a_into,b);
    }
}

我可以实现(B):

#[derive(Debug)]
pub enum PointIntoError<T> {
    ErrorInX(T),ErrorInY(T),}

impl<FromType,ToType> TryInto<(ToType,ToType)> for Point2D<FromType>
    where FromType: TryInto<ToType>,FromType: copy {
    type Error = PointIntoError<FromType>;

    fn try_into(self) -> Result<(ToType,ToType),Self::Error> {
        let x_ = self.0.try_into();
        let y_ = self.0.try_into();

        match x_ {
            Ok(x) => {
                match y_ {
                    Ok(y) => Ok((x,y)),_ => Result::Err(PointIntoError::ErrorInY(self.1))
                }
            }
            _ => Result::Err(PointIntoError::ErrorInX(self.0))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn try_into() {
        let a: Point2D<u32> = Point2D(400,400);
        let a_into :(u16,u16) = a.try_into().expect("Could not convert to tuple of u16");
        let b: (u16,u16) = (400,400);
        assert_eq!(a_into,b);
    }

    #[test]
    #[should_panic]
    fn try_into_fail() {
        let a: Point2D<u32> = Point2D(400,400);
        let a_into :(u8,u8) = a.try_into().expect("Could not convert to tuple of u8");
    }
}

当单独运行时,两个测试都通过。但是,当我尝试编译两个 impl 时,我得到:

error[E0119]: conflicting implementations of trait `std::convert::TryInto<(_,_)>` for type `Point2D<_>`:
  --> src/lib.rs:31:1
   |
31 | / impl<FromType,ToType)> for Point2D<FromType>
32 | |     where FromType: TryInto<ToType>,33 | |           FromType: copy {
34 | |     type Error = PointIntoError<FromType>;
...  |
49 | |     }
50 | | }
   | |_^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T,U> std::convert::TryInto<U> for T
             where U: TryFrom<T>;

error: aborting due to prevIoUs error

For more information about this error,try `rustc --explain E0119`.

错误不是特别有用,但我猜对于实现 TryInto 的结构,Into 有某种认实现,因此我无法同时定义两者。

>

同时支持Into 转换和TryInto 转换的最惯用的方式是什么?我想我总是可以使用 .tryInto.expect,当我确定类型匹配但它看起来不整齐时。

解决方法

我猜对于实现 Into 的结构体来说,TryInto 有某种默认实现,因此我不能同时定义两者。

这是正确的,更具体地说,对于任何实现 TryFrom 的结构都有一个 Into 的全面实现(它是为任何实现 From 的结构全面实现的):https://doc.rust-lang.org/std/convert/trait.TryFrom.html#impl-TryFrom%3CU%3E

支持 Into 转换和 TryInto 转换的最惯用的方法是什么?我想我总是可以 .tryInto 和 .expect 当我确定类型匹配但它看起来不整齐时。

我认为最惯用的方法是将您的 Into 实现转换为普通方法,例如.into_tuple(),这是一个相当常见的模式,例如 slice::into_vecString::into_boxed_str

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。