![](/img/trans.png)
[英]Is it possible to create a type alias that has trait bounds on a generic type for a function?
[英]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 具有某些行為時,請添加特征界限。
如果您需要MyStruct
是Clone
,那么它擁有的所有東西也必須是 Clone,所以T: Clone
才有意義。
但是,如果不需要,最好不要包含此類特征限制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.