Borrow<Borrowed: ?Sized>トレイトとToOwnedトレイト

Stringの借用は、&strとして、&strの所有は、Stringとして表すことが出来る。

Rustでは、こういった関係をBorrow<Borrowed: ?Sized>ToOwnedトレイトを使って表すことが出来る。

Note: 参照 - ある所有された値への借用を表す型。コピーセマンティックである。

trait Borrow<Borrowed: ?Sized>

別の型への参照を生成する。

T&Borrowed

BorrowedBorrowする型とよめる

pub trait Borrow<Borrowed>
where
    Borrowed: ?Sized,
{
    fn borrow(&self) -> &Borrowed;
}

f:id:yossan2:20210130161626p:plain

String = Borrow<str>

f:id:yossan2:20210130161825p:plain

impl Borrow<str> for String {
    fn borrow(&self) -> &str {
        &sef[...]
    }
}

Vec<T> = Borrow<[T]>

f:id:yossan2:20210130164100p:plain

Box<T> = Borrow<T>

f:id:yossan2:20210130161919p:plain

Borrowの役割

HashMapにおいて、getメソッドは以下のように定義されている。

impl <K, V, S> HashMap<K, V, S>
where
    K: Eq + Hash,
    S: BuildHasher,

    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq,
  • K: Borrow<Hash + Eq>

これによってキーの型がStringでもBorrow<str>型に型が弱めることができている。

use std::collections::HashMap;
let mut contacts = HashMap::new();
contacts.insert(String::from("Tanaka"), String::from("062-2222-3333"));
contacts.insert(String::from("Yoshida"), String::from("055-1234-5467"));

// &strで値を取り出せる
dbg!(contacts.get("Yoshida"))

trait ToOwned

pub trait ToOwned {
    type Owned = Borrow<Self>;
    fn to_owned(&self) -> Self::Owned;
}

f:id:yossan2:20210130162528p:plain

Cloneトレイトが&TからTへの変換に対して、ToOwnedトレイトは、Tから特定の型(Borrow<T>)への変換。

実装している型

  • str
  • [T]
  • Path

str

impl ToOwned for str {
    type Owned = String; //  Borrow<Self> である必要がある
    fn to_owned(&self) -> String
}

f:id:yossan2:20210130162546p:plain

[T]

impl ToOwned for [T]
where
    T: Clone,
{
    type Owned = Vec<T>;
    fn to_owned(&self) -> Vec<T>
}

f:id:yossan2:20210130162607p:plain

Path

impl ToOwned for Path {
    type Owned = PathBuf;
    fn to_owned(&self) -> PathBuf
}

f:id:yossan2:20210130162618p:plain