【问题标题】:How to fix error with generic function in rust如何使用 rust 中的通用函数修复错误
【发布时间】:2021-06-22 07:51:44
【问题描述】:

我正在尝试理解 Rust 中的泛型。我无法理解这里出了什么问题

fn say<T>(msg: &T)  {
    let slen = msg.chars().count();
    if slen > 0 {
        println!("Char Count {} " ,slen);
    } 
}


fn main() {
    let msg = String::from("Hello World from Rust!!!");
    say::<String>(&msg);
}

编译错误:

error[E0599]: no method named `chars` found for reference `&T` in the current scope
 --> hell.rs:4:20
  |
4 |     let slen = msg.chars().count();
  |                    ^^^^^ method not found in `&T`

【问题讨论】:

  • say&lt;T&gt; 表示“对于任何T,此方法都可以使用。”不保证任意类型都有chars 方法,所以泛型在这里不起作用。
  • 非常感谢您的回复。如何使这项工作。在调用函数时也没有提示 无济于事?
  • 如果您的泛型仅适用于特定类型,那么它将不起作用。只是不要使用泛型,而是使用&amp;str

标签: generics rust


【解决方案1】:

Rust 泛型背后的想法是泛型类型既受特征界限 的限制和定义。由一组特征绑定的T 上的泛型函数可能会假设T 具有来自这些特征的方法,仅此而已。由于 T 不受任何 trait 约束,因此没有可调用的 T::chars() 方法。

要编写调用任何现有 trait 未提供的方法的通用代码,例如 chars(),您可以编写自己的 trait 来提供所需的功能,并为您需要的类型实现它。例如:

trait CharCount {
    fn char_count(&self) -> usize;
}

impl CharCount for String {
    fn char_count(&self) -> usize {
        self.chars().count()
    }
}

有了这个特性,你可以编写你的泛型方法来使用它:

fn say<T: CharCount>(msg: &T)  {
    let slen = msg.char_count();
    if slen > 0 {
        println!("Char count: {}", slen);
    } 
}

您可以使用String 调用say,也可以使用决定实现CharCount 特征的任何其他类型,即使它是您在编写该特征时没有想到的类型。

【讨论】:

  • 这个答案出来的时候非常巧合,我也来寻找类似的解决方案。接受您的解决方案作为答案trait Dummy { fn len(&amp;self) -&gt; usize; } impl Dummy for String { fn len(&amp;self) -&gt; usize { return self.chars().count(); } } fn say&lt;T: Dummy&gt;(msg: T) { let slen = msg.len(); if slen &gt; 0 { println!("Char Count {} " ,slen); } } fn main() { let msg=String::from("Hello World from Rust!!!"); say::&lt;String&gt;(msg); }
【解决方案2】:

您的函数say 假定输入有一个chars 方法,该方法在chars 上创建一个迭代器。这适用的类型并不多,因此使其通用化似乎不是很有用。

具有chars 迭代器方法的主要两种类型是String&amp;str。如果您将参数更改为&amp;str,那么您可以接受其中任何一个:

fn say(msg: &str)  {
    let slen = msg.chars().count();
    if slen > 0 {
        println!("Char Count {} ", slen);
    } 
}


fn main() {
    let msg: String = String::from("Hello World from Rust!!!");
    say(&msg);
    let msg: &str = "Hello World from Rust!!!";
    say(msg);
}

另见:

【讨论】:

  • 或者,如果您想使用泛型/特征,您可以使用T: AsRef&lt;str&gt;
  • 感谢 Peter 分享链接以参考有用的字符串
猜你喜欢
  • 1970-01-01
  • 2016-11-14
  • 2019-09-24
  • 2021-11-17
  • 2019-07-28
  • 2021-06-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多