Newtype pattern error: cannot move out of dereference of

Newtype pattern error: cannot move out of dereference of

我想围绕现有 type/struct 创建一个包装器。根据 Newtype 模式,根据 Rust Book ch 19,“在 Wrapper 上实现 Deref 特性到 return 内部类型将提供对所有底层方法的访问”:

https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

这是我对字符串的包装器的实现。一个简化的例子:

struct Wrapper(String);

impl Deref for Wrapper {
    type Target = String;

    fn deref(&self) -> &Self::Target {
        &self.0 //pointer to Inner value
    }
}

但是,调用一个消耗 self 的方法会抛出错误:

fn main() {
    let d = "Dog".to_string();
    let w = Wrapper(d);
    w.into_bytes();
}

错误:无法从 Wrapper 的解引用中移出,因为值的类型为 std::string::String,它没有实现 Copy 特征

因此我有两个问题:

  1. 我的实现有什么问题,如何让它发挥作用?
  2. 我想让它与 self、&self、mut self 和 &mut self 方法一起正常工作。如何适当地实施 DerefMut?

What is wrong with my implementation and how do make it work?

String::into_bytes 移动 String,在你的情况下你只能访问它的引用 &,所以你不能移动它。

您可以使用 bytes 其中 returns 一个字节的迭代器而不移动它:

fn main() {
    let d = "Dog".to_string();
    let w = Wrapper(d);
    let b = w.bytes();
    println!("{b:?}");
}

I'd like to make it work properly with self, &self, mut self, &mut self methods. How do I also implement DerefMut appropriately?

您需要考虑签名,一般来说:

  • Deref -> 得到一个 &T
  • DerefMut -> 得到一个 &mut
  • From/Into -> 将类型转换为其他类型的拥有版本 T

示例使用 From/Into:

struct Wrapper(String);

impl From<Wrapper> for String {
    fn from(w: Wrapper) -> String {
        w.0
    }
}

fn main() {
    let d = "Dog".to_string();
    let w = Wrapper(d);
    let s: String = w.into();
    let bytes = s.into_bytes();
    println!("{bytes:?}");
}

Playground

您还可以考虑查看 std::borrow 模块,它具有允许您像其他类型一样使用您的类型的特性。

最后,您的方法可能会奏效,但如前所述,在这种情况下您不能从 &T 转到 U(您可以 T 转到 U) .剩下的解决方案是 Clone 并创建一个拥有的副本:

use std::ops::Deref;

struct Wrapper(String);

impl Deref for Wrapper {
    type Target = String;

    fn deref(&self) -> &Self::Target {
        &self.0 //pointer to Inner value
    }
}

fn main() {
    let d = "Dog".to_string();
    let w = Wrapper(d);
    let b = w.deref().clone().into_bytes();
    println!("{b:?}");
}

Playground