簡體   English   中英

為什么在具有泛型類型參數的結構定義中使用特征邊界?

[英]Why use trait bounds in struct definitions with generic type parameters?

我可以定義一個結構類型,它使用具有特征綁定的泛型類型參數:

struct MyStruct<T: Clone> {
    field: T,
}

這使我無法使用不符合特征界限的泛型實例化MyStruct

// Note: does not implement Clone
struct UnitStruct;

fn main() {
    // ERROR: Unsatisfied trait bound: UnitStruct: Clone
    let s = MyStruct { field: UnitStruct };
}

但是為什么我要這樣定義我的結構呢? MyStruct的實例化施加此類限制的用例是什么?

我注意到即使在MyStruct定義中使用特征綁定,如果我定義一個使用MyStruct的接口,我仍然必須重復特征綁定:

// This works
fn func<T: Clone>(s: MyStruct<T>) -> T { s.field.clone() }

// This does not. Compiler demands a trait bound for `T`
fn func<T>(s: MyStruct<T>) -> T { s.field.clone() }

通常,您希望盡可能避免向結構添加特征邊界。 當您以這種方式添加特征邊界時,您將不得不在impl<T: A + B + C + Etc> for Foo<T>上再次寫出特征邊界。 這對您來說是更多的工作,如果不是所有這些特征對於您正在編寫的impl塊實際上都是必需的,甚至會降低可讀性。 Clone這樣沒有關聯類型的特征或 static 函數可能不應該包含在類型范圍中,除非您有特定的理由這樣做。

您可以以這種方式添加特征邊界的原因是因為它可以大大提高可讀性,並且在某些情況下它在很大程度上是不可避免的,例如關聯類型或必須為Sized的字段。

use std::sync::mspc::Receiver;

trait FooProcessor {
    type Input: Sized + Send;
    type Output: Sized;

    fn do_foo(&mut self, input: Self::Input) -> Self::Output;
}


struct FooHandler<P: FooProcessor> {
    processor: P,
    input_channel: Receiver<P::Input>,
    outputs: Vec<P::Output>,
}

我們可以通過擴展以添加更多類型參數來避免這種情況,但這很快就會變得混亂。 這會大大降低代碼的可讀性,如果您有多個嵌套的通用結構,情況會變得更糟。

struct FooHandler<P, I, O> {
    processor: P,
    input_channel: Receiver<I>,
    outputs: Vec<O>,
}

另一個很重要的原因是避免錯誤。 如果類型在泛型字段中沒有意義,那么您可以通過在結構參數上強制執行它來讓編譯器及早捕獲它。 圍繞使用Foo<Bar>的想法編寫代碼只是為了發現Bar實際上從來不是一個有效的選項,這感覺不是很好。

trait bound 限制了可以在泛型函數或結構中使用的類型,但也使泛型 T 能夠做它本來不能做的事情。

例如

/// This function doesn't compile, because T cannot be cloned
fn clone_and_return1<T>(t: &T) -> T {
    t.clone()
}

/// This compiles, because we limit T to types that implements Clone
fn clone_and_return2<T>(t: &T) -> T
where
    T: Clone,
{
    t.clone()
}

因此,當您需要 T 具有某些行為時,請添加特征界限。

如果您需要MyStructClone ,那么它擁有的所有東西也必須是 Clone,所以T: Clone才有意義。

但是,如果不需要,最好不要包含此類特征限制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM