【问题标题】:Reverse generic constraint with Borrow trait具有借用特征的反向通用约束
【发布时间】:2020-02-02 16:39:04
【问题描述】:

我是 rust 新手,我刚刚了解了 Borrow 特征。
据我了解,Borrow 特征暴露了一个函数borrow,它的工作原理就像借用(即&),但你也可以在通用约束中使用它(你不能用正常的借用语法来做) .

我有这个功能

pub fn get<Q>(&self, key: &Q) -> Option<&V>
    where K: Borrow<Q>,
          Q: Hash + Eq + ?Sized
{
    let bucket = self.bucket_key(key);
    self.buckets[bucket].iter().find(|&(ref ekey, _)| ekey.borrow() == key).map(|&(_, ref v)| v)
}

(我在 YouTube 上观看了 Jon Gjengset 的视频)

对我来说奇怪的是,我们将结构上定义的K 类型限制为像Borrow&lt;Q&gt; 一样工作。

所以我想知道这个约束究竟对KQ 说了什么。
这是否意味着我们将K 约束为像Borrow&lt;Q&gt; 一样,或者K 在这里固定(因为它已经在结构上定义)并且我们正在约束Q(在幕后Rust将其转换为 Q: Unborrow&lt;K&gt; 之类的东西或类似的东西)。

我希望我说得通。我通常使用 C#,这样的东西没有意义。

【问题讨论】:

    标签: rust


    【解决方案1】:

    我假设您指的是HashMap::get

    不要想太多。 Rust trait 系统基本上是一种逻辑,trait bound 就像逻辑约束;这里的类型签名说:

    • Q 必须是 HashEq?Sized
    • K 必须能够以Q 借用

    实际上是为了方便:

    use std::collections::HashMap;
    
    fn main() {
        let mut map = HashMap::new();
        map.insert(String::from("a"), 1u32);
        map.insert(String::from("b"), 2);
    
        assert_eq!(map.get("a"), Some(&1));
    }
    

    这里的map 变量是HashMap&lt;String, u32&gt; 类型。如果不是Borrow,你就得写:

    map.get(&String::from("a"))
    

    但由于String 可以借用为str"a"&amp;'static str 类型,你可以写:

    map.get("a")
    

    The trait Borrow documentation 有更详细的解释。

    【讨论】:

    • 这是一个 HashMap,是我自己根据指南编写的。我理解约束的概念,因为它们存在于 C# 中,但令我困惑的是 K 是结构级别的泛型,Q 是函数级别的泛型,这让我感到困惑,你可以约束 K在函数级别,因为一旦创建了 HashMap 结构,它就应该已经很好地定义了
    • @areller 函数可以进一步约束现有的泛型类型,例如本例中的K。这意味着如果您使用带有K 而不是Borrow&lt;Q&gt; 的hashmap,那么尽管您可以使用hashmap 的任何其他函数,但您不能调用map.get(...)。本质上,这是提供此功能的类型的可选功能。
    • @FilipeRodrigues 很好的解释。谢谢!
    • @FilipeRodrigues 不正确。由于T 的值始终可以作为T 借用,因此get 函数始终可用。使用Borrow,它可以接受比&amp;K更多的参数类型。
    • @edwardw 好点,但这仅适用于Borrow(以及其他具有诸如此类的全面实现的特征),但是您可以在函数级别(或者如果@ 987654354@ 是严格级别的泛型),这会使函数不可用,这是进一步限制的点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2017-06-24
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多