【问题标题】:Why does String::from(*d) give a different result from *d.to_string() on a &&str?为什么 String::from(*d) 在 &&str 上给出与 *d.to_string() 不同的结果?
【发布时间】:2018-03-01 22:14:47
【问题描述】:

我有点疑惑为什么在第二种情况下取​​消引用 &&str 似乎不起作用:

use std::collections::HashSet;

fn main() {
    let days = vec!["mon", "tue", "wed"];
    let mut hs: HashSet<String> = HashSet::new();

    for d in &days {
        // works
        hs.insert(String::from(*d));

        // doesn't
        hs.insert(*d.to_string());
    }
    println!("{:#?}", hs);
}

str 确实实现了 ToString 特征,但它仍然给我错误:

error[E0308]: mismatched types
  --> src/main.rs:12:19
   |
12 |         hs.insert(*d.to_string());
   |                   ^^^^^^^^^^^^^^ expected struct `std::string::String`, found str
   |
   = note: expected type `std::string::String`
              found type `str`

我在这里弄错了什么语法?

Rust Playground Link

【问题讨论】:

  • 注意函数调用的优先级高于deref; *d.to_string() 将取消引用应用于调用结果。

标签: rust


【解决方案1】:

to_string 在取消引用之前被调用到 d,因此您将取消引用 String,这将导致 str

改成

hs.insert(d.to_string());

这是可行的,因为d 会自动取消引用为str,之后将转换为String。这称为Deref coercions

如果你有一个 U 类型,并且它实现了 Deref&lt;Target=T&gt;&amp;U 的值将自动强制转换为 &amp;T

...

Deref 也会在调用方法时生效

这是exactly the case hereimpl Deref&lt;Target = str&gt; for String。见here for an example:

&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;&amp;Foo 类型的值仍然可以调用在 Foo 上定义的方法,因为编译器将插入尽可能多的 * 操作以使其正确。并且由于它插入了*s,因此使用了Deref

example 证明了这一点:

struct Foo;

impl Foo {
    fn foo(&self) { println!("Foo"); }
}

let f = &&Foo;

// prints "foo"
f.foo();

顺便说一句,

hs.insert((*d).to_string());

也将work,因为它首先被引用到&amp;str

【讨论】:

  • @SebastianRedl 的评论和你回答的最后一行让我明白了。 Deref 强制需要一些时间来适应...谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多