当我尝试在未大小的类型上手动实现 Ord 和 Eq 时,为什么会得到一个 `trait bound `[T]: std::marker::Sized` 不满足? [英] Why do I get a `trait bound `[T]: std::marker::Sized` is not satisfied when I try and implement Ord and Eq manually on unsized types?

查看:69
本文介绍了当我尝试在未大小的类型上手动实现 Ord 和 Eq 时,为什么会得到一个 `trait bound `[T]: std::marker::Sized` 不满足?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当创建一个存储 DST 的结构体(例如,原始切片)时,我可以使用普通的 #[derive(Eq, PartialEq, Ord, PartialOrd)] 工具来获得这个实现我的类型特征:

When creating a struct which stores a DST (e.g., a raw slice), I can use the normal #[derive(Eq, PartialEq, Ord, PartialOrd)] facility to get implementations of this trait on my type:

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct A([u8]);

然而,如果我手动实现它们,那么编译器会抱怨我的类型没有实现Sized:

However, if I implement them manually, then the compiler will complain that my type does not implement Sized:

struct A([u8]);

impl AsRef<[u8]> for A {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl<S: AsRef<[u8]>> PartialEq<S> for A {
    fn eq(&self, other: &S) -> bool {
        self.0.eq(other.as_ref())
    }
}

impl Eq for A { }

impl<S: AsRef<[u8]>> PartialOrd<S> for A {
    fn partial_cmp(&self, other: &S) -> Option<Ordering> {
        let  slice: &[u8] = &self.0;
        slice.partial_cmp(other.as_ref())
    }
}

impl Ord for A {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(&other).unwrap()
    }
}

编译结果:

rustc 1.12.0 (3191fbae9 2016-09-23)
error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
  --> <anon>:20:6
   |
20 | impl Eq for A { }
   |      ^^
   |
   = note: `[u8]` does not have a constant size known at compile-time
   = note: required because it appears within the type `A`
   = note: required because of the requirements on the impl of `std::cmp::PartialEq` for `A`
   = note: required by `std::cmp::Eq`

error[E0277]: the trait bound `[u8]: std::marker::Sized` is not satisfied
  --> <anon>:29:6
   |
29 | impl Ord for A {
   |      ^^^
   |
   = note: `[u8]` does not have a constant size known at compile-time
   = note: required because it appears within the type `A`
   = note: required because of the requirements on the impl of `std::cmp::PartialOrd` for `A`
   = note: required by `std::cmp::Ord`

如果我创建了一个确实具有固定大小的类型的变体(例如,通过将其转换为固定大小的数组),那么我可以手动实现这些特征没有问题.

If I create a variant of the type which does have a fixed size (e.g. by turning it into a fixed-size array), then I can manually implement the traits no problem.

struct B([u8; 5]);

impl AsRef<[u8]> for B {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl<S: AsRef<[u8]>> PartialEq<S> for B {
    fn eq(&self, other: &S) -> bool {
        self.0.eq(other.as_ref())
    }
}

impl Eq for B { }

impl<S: AsRef<[u8]>> PartialOrd<S> for B {
    fn partial_cmp(&self, other: &S) -> Option<Ordering> {
        let  slice: &[u8] = &self.0;
        slice.partial_cmp(other.as_ref())
    }
}

impl Ord for B {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(&other).unwrap()
    }
}

这是一个显示问题的游乐场链接.

我的问题是 - 我如何在我的自定义 DST 上实现 OrdEq,以便我可以利用我可以 partial_cmp/eq 通过任何 AsRef<[u8]>,但也可以使用它来强制 Ord/Eq trait 的边界实现,就像我在示例中对 struct B 所做的那样?

My question is - how do I implement Ord and Eq on my custom DST, so that I can take advantage of the fact that I can partial_cmp/eq by any AsRef<[u8]>, but also use that to enforce the bounds for the Ord/Eq trait implementations, as I do with struct B in my example?

推荐答案

问题在于 S: AsRef<[u8]> 也将 S 限制为 Sized 类型默认.您需要使用 ?Sized 来选择退出.

The problem is that S: AsRef<[u8]> is also restricting S to Sized types by default. You need to use ?Sized to opt-out of that.

所有泛型类型参数都隐式地具有 Sized 绑定,因此 ?Sized 可用于选择退出隐式绑定.

All generic type parameters implicitly have the Sized bound, so the ?Sized can be used to opt-out of the implicit bound.

来自 Rust 手册.

以下对我来说编译得很好:

The following compiles fine for me:

use std::cmp::Ordering;

struct A([u8]);

impl AsRef<[u8]> for A {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl<S: AsRef<[u8]> + ?Sized> PartialEq<S> for A {
    fn eq(&self, other: &S) -> bool {
        self.0.eq(other.as_ref())
    }
}

impl Eq for A {}

impl<S: AsRef<[u8]> + ?Sized> PartialOrd<S> for A {
    fn partial_cmp(&self, other: &S) -> Option<Ordering> {
        let slice: &[u8] = &self.0;
        slice.partial_cmp(other.as_ref())
    }
}

impl Ord for A {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(&other).unwrap()
    }
}

演示

这篇关于当我尝试在未大小的类型上手动实现 Ord 和 Eq 时,为什么会得到一个 `trait bound `[T]: std::marker::Sized` 不满足?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆