【问题标题】:Calling T::new() from inside generic struct in Rust从 Rust 中的泛型结构内部调用 T::new()
【发布时间】:2021-03-29 00:18:26
【问题描述】:

停下!我是一个生锈的新手,在过去的几天里我经历了很多事情,但找不到任何关于此的信息。 我有一个通用结构(我已经简化以说明问题)。我希望能够创建一个结构,它使用 std::collections::HashMap 、 HashSet 、 List 等来做很多事情 我假设我需要暗示 T 必须实现一个新方法..使用一个特征?或类似的,但搜索只会找到基本的东西

public struct dude< T > {
    data : std::sync::Arc< T >,
}

impl < T > dude< T > {
    pub fn new() -> dude< T > {
        Reloader{ data : Arc::new( <T>::new() ) }
    }
}

产生以下错误:

<T>::new();
     ^^^ function or associated item not found in `T`

【问题讨论】:

  • 我也试过 T::new();这会产生相同的错误:-(

标签: generics rust


【解决方案1】:

当您在 rust 中的泛型上使用函数时,您需要指定提供这些函数的 trait bound。

例如,如果我尝试使用不提供 new 函数的类调用 Dude::new() 怎么办?在某些语言(如 C++)中,这将被标记为您尝试实际创建实例的错误 - 但在 rust 中,存在推理局部性原则。

有一个现有的 trait 提供像 new() - Default 这样的功能 - 它提供 Default::default() 使用它作为 trait bound 看起来像这样:

use std::sync::Arc;
pub struct Dude<T> {
    data : std::sync::Arc<T>,
}

impl<T:Default> Dude<T> {
    pub fn new() -> Dude<T> {
        Dude{ data : Arc::new( Default::default() ) }
    }
}

Default trait 已经为许多类型实现,对于任何自定义类型,您都可以轻松派生它(clippy 甚至会警告您在很多地方都没有实现它)。

现在我可以写了:

let dude: Dude<String> = Dude::new();

Dude 实现这个可能也有意义,而不是在Dude 本身内部提供新的。

impl<T:Default> Default for Dude<T> {
  fn default() -> Dude<T> {
    Dude{ data : Arc::new( Default::default() ) }
  }
}

【讨论】:

  • 你的答案解释了如何做到这一点,但显然应该建议使用像 Def​​ault 这样的特征,而不是引入 std 中已经存在的新特征。
  • 同意 - 不知何故,我忘记了一些像默认值一样简单的事情。我现在就解决这个问题。
  • 完美 - 就像买的一样工作,谢谢迈克尔 :)
  • @Stargateur 我的意思是,默认设置很棒,但不要只见树木不见森林。默认当然是制作具有零参数的对象的一种方法,但是也有无数其他方法可以制作具有零参数的对象,这可能不是默认的。在许多情况下,接受一个函数来调用以获取对象允许例如咖喱构造函数。
  • @GManNickG 我没有说使用泛型函数不好......我只是在谈论新特性。常见的模式是为此类功能使用_with 方法,如doc.rust-lang.org/std/vec/struct.Vec.html#method.resize_with
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
相关资源
最近更新 更多