【问题标题】:Why does T not implement AsRef<T>?为什么 T 不实现 AsRef<T>?
【发布时间】:2018-02-20 14:24:01
【问题描述】:

此代码无法编译:

fn ref_on_int<T>(_: T) where T: AsRef<i32> {}

fn main() {
    ref_on_int(&0_i32)
}

因为

the trait bound `i32: std::convert::AsRef<i32>` is not satisfied

为什么会这样?

这可能很有用,例如像这样的新类型

struct MyInt(i32);

impl AsRef<i32> for MyInt {
    /* etc. */
}

那么您可以无所谓地传递i32 上的引用或MyInt 上的引用,因为在内存中我们在这两种情况下都有i32

【问题讨论】:

  • 我认为这就是Borrow 的用途。我不完全确定AsRefBorrow 之间的区别,但后者是为&amp;T 实现的。
  • @rodrigo 哦,好的。您可以将其发布为答案吗?
  • @rodrigo AsRef 似乎在这里更合适,因为第二个示例包括转换。
  • @ljedrz 对不起,这不是目标,我会改变我的问题。

标签: rust


【解决方案1】:

AsRefBorrow 乍一看非常相似,但它们用于不同的事物。 The Book 很好地描述了它们之间的区别:

当您想抽象不同种类的 借用,或者当你构建一个处理拥有的数据结构时 并以等效方式借用值,例如散列和 比较。

如果您想将某些内容转换为参考,请选择 AsRef 直接,你正在编写通用代码。

在您的情况下,Borrow 是一个更合理的选择,因为不涉及转换。

至于为什么AsRef 没有在不同的整数类型之间实现的问题,我想这违背了Rust 表达强制转换的意图;我认为这类似于Why can't I compare two integers of different types?的问题。

【讨论】:

  • 但问题不是为什么AsRef不在不同的整数类型之间实现?而是为什么AsRef&lt;T&gt;不为&amp;T实现我>?
  • @rodrigo true - 我只是指问题的原始状态,这是 IMO 在这个问题上的一个有趣转折。
  • @ljedrz:你如何在积分之间实现AsRef?要返回&amp;i64,您需要将i64 存储在某处,当您只有i32 时,您无法从以太中召唤它:x
  • @MatthieuM。我在考虑大小相同的情况,例如从u32 获取&amp;i32;当然,您对不同尺寸的看法是对的。
【解决方案2】:

这是authoritative answer by Aaron Turon

Borrow 提供了一个全面的实现T: Borrow&lt;T&gt;,这对于使上述集合正常工作必不可少AsRef 提供了不同的一揽子实现,基本上是&amp;T: AsRef&lt;U&gt; 每当T: AsRef&lt;U&gt;,这对于像fs::open 这样可以使用更简单和更灵活的签名的API 很重要。由于连贯性,您不能同时拥有两种全面实现,因此每个特征都在做出适合其用例的选择。

【讨论】:

    【解决方案3】:

    我认为这是AsRefBorrow 的区别之一。

    Borrow&lt;T&gt;直接为&amp;T实现,而AsRef&lt;T&gt;不为&amp;T实现。

    有趣的是,如果 T 实现了 AsRef&lt;U&gt;,则 AsRef&lt;U&gt; 是为 &amp;T 实现的。也就是说,如果您可以将AsRef 与一个类型一起使用,那么您可以将它与对同一时间的引用一起使用。

    另一个有趣的事情是Borrow&lt;T&gt; 是为&amp;T 实现的,但也为T 实现!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-04
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      相关资源
      最近更新 更多