将 1 元组结构转换为包含的元素的惯用方法是什么?

What is the idiomatic way to convert a 1-tuple struct to the contained element?

假设我们有以下类型:

struct Wrapper(Content);

说我经常需要访问这个类型的 Content 值,每次解构它很快就会变得很麻烦。展开这个值的惯用方法是什么?我知道两种方法:实施 Into<Content> 和实施 Deref。也许其中之一是首选?或者也许有一些更容易接受的方法来做到这一点?

进入方法:

impl Into<Content> for Wrapper {
    fn into(self) -> Content {
        let Wrapper(content) = self;
        content
    }
}

// ...

let content: Content = wrapper.into();

取消引用方法:

impl Deref for Wrapper {
    type Target = Content;

    fn deref(&self) -> &Self::Target {
        let Wrapper(content) = self;
        content
    }
}

// ...

let content: Content = *wrapper;

访问元组或元组结构元素的最简单方法是使用 . 语法:

impl Wrapper {
    fn as_content(&self) -> &Content {
        &self.0
    }
}

请注意,在元组结构中,.0 伪字段默认是私有的,就像任何其他结构字段一样。如果你想让它成为 public,这样你就不需要 impl Deref,使用这个语法:

pub struct Wrapper(pub Content);

至于惯用的,当一个类型可以看作是对其他类型的引用时,习惯上有一个函数as_type,如上。如果它可以 unwrapped 成那个类型,那么 into_type:

fn into_content(self) -> Content {
    self.0
}

您也可以考虑实施 AsRef<Content> and/or Into<Content>,但这取决于预期用途。

Deref 绝对 不是 惯用语。引用 the docs:

Implementing Deref for smart pointers makes accessing the data behind them convenient, which is why they implement Deref. On the other hand, the rules regarding Deref and DerefMut were designed specifically to accommodate smart pointers. Because of this, Deref should only be implemented for smart pointers to avoid confusion.

只要wrapper类型不是智能指针即可(这个定义在不断变化;there is a very long discussion in the users forum about this subject。不过,通常wrapper类型不是智能指针,很容易判断)。

直接实现 Into 也不是惯用的。您应该改为实施 From 。再次引用 the docs:

One should avoid implementing Into and implement From instead. Implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.

我们还有什么?

  • 实施 AsRef, AsMut and From 以实现转化。
  • 使用解构:let Wrapper(v) = wrapper;.
  • 使用点语法直接引用字段:wrapper.0.

我建议根据需要实现转换特征 AsRefAsMutFrom,但在不使用泛型时使用解构或点语法。使用哪个取决于您的意见——Rust 社区对此没有强有力的约定。