我该如何为枚举类型实现Borrow、ToOwned或Deref?(这是一个提问标题,不需要回答)

9

我有一个类,看起来像这样:

enum Name<'a> {
    Single(&'a str),
    Double(&'a str, &'a str),
}

还有另一种非常相似的类型,长这样:

enum OwnedName {
    Single(String),
    Double(String, String),
}

我已经有一种将Name转换为OwnedName的方法。但是,我无法想出一种实现类似于DerefBorrow的方式来将OwnedName转换回Name。这意味着我必须写两次相同的方法,这很烦人。我希望有一些东西可以模仿PathBuf/PathString/str的工作方式。我尝试了以下代码:

impl ops::Deref for OwnedName {
    type Target = Name;

    fn deref(&self) -> &Name {
        match *self {
            OwnedName::Single(ref s) => Name::Single(&**s),
            OwnedName::Double(ref s1, ref s2) => Name::Double(&**s1, &**s2),
        }
    }
}

这个错误是关于 type Target = Name 的生命周期参数数量错误:期望 1 个,但找到了 0 个。这很容易理解,因为它需要一个生命周期。但我无法提供。那么有没有办法让我以这种方式使用 DerefBorrowToOwned 呢?


你的类型是否与 str 相同,比较和哈希方式是否一致?如果不是,则无法实现 Borrow<str> - bluss
这是一般规则还是你特别给我建议? :) 我不能像 str 一样比较和哈希相同,因为我的一个变量中有两个字符串。 - Ben S
这是“Borrow” impls 需要遵守的规则(由 Borrow 记录)。我所说的“can't”实际上是指“绝对不应该”。 - bluss
2个回答

7

无法做到这一点。

请注意,Deref :: deref 的签名表示它想要一个指向与被取消引用的事物相同生命周期的 Name 指针。这样的值不存在。您也不能在 deref 函数中返回指向您创建的内容的指针,因为它不可能超过其自己的堆栈帧。

根本问题是 Name 基本上是不同的指针类型(就像 *const T 是对 &T 的引用),但是 Deref 和其他类似的特征只允许您返回借用的指针。目前,这没有任何解决方法。

但是,如果您只是不使用 Deref 和其他类似的特征,则可以执行此操作。一种可能性是:impl<'a> From<&'a OwnedName> for Name<'a>


2
实际上,从Deref::deref函数中返回在函数内创建的值是有可能的:这个值必须是一个fat指针。这就是PathBuf上的Deref实现方式 - 它返回一个指向未定长的Path结构体的fat指针&Path。当然,这仅限于指向未定长类型的指针,并且不幸的是,对于OwnedName类型,无法编写等效的未定长枚举,因此这种方法在这种情况下行不通。 - Vladimir Matveev
好的,我明白了。我试图模拟 PathBuf 中未指定大小的 Path 类型 - 如果我想要这样做,我必须在这里使用 str 而不是 &str,但在我的特定枚举中我无法这样做。 - Ben S

6

我同意@DK的观点。只是补充一下,如果你的想法是可以互换使用它们,你可能根本不需要有一个OwnedName。 你可以定义Name来接受&strString

enum Name<T> where T:Borrow<str> {
    Single(T),
    Double(T, T),
}

// these both work now
let _a1 = Name::Single("hello");
let _a2 = Name::Double(String::from("hello"), String::from("world"));

好主意,我没有想到。 - Ben S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接