man*_*anu 14 generics struct rust
我有一个MyStruct
采用泛型参数的结构,T: SomeTrait
我想new
为MyStruct
. 这有效:
/// Constraint for the type parameter `T` in MyStruct
pub trait SomeTrait: Clone {}
/// The struct that I want to construct with `new`
pub struct MyStruct<T: SomeTrait> {
value: T,
}
fn new<T: SomeTrait>(t: T) -> MyStruct<T> {
MyStruct { value: t }
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
我想把这个new
函数放在一个impl
像这样的块中:
impl MyStruct {
fn new<T: SomeTrait>(t: T) -> MyStruct<T> {
MyStruct { value: t }
}
}
Run Code Online (Sandbox Code Playgroud)
但这无法编译:
error[E0107]: wrong number of type arguments: expected 1, found 0
--> src/main.rs:9:6
|
9 | impl MyStruct {
| ^^^^^^^^ expected 1 type argument
Run Code Online (Sandbox Code Playgroud)
如果我试着这样说:
impl MyStruct<T> {
fn new(t: T) -> MyStruct<T> {
MyStruct { value: t }
}
}
Run Code Online (Sandbox Code Playgroud)
错误更改为:
error[E0412]: cannot find type `T` in this scope
--> src/main.rs:9:15
|
9 | impl MyStruct<T> {
| ^ not found in this scope
Run Code Online (Sandbox Code Playgroud)
如何提供通用结构的实现?我在哪里放置通用参数及其约束?
And*_*kin 16
类型参数<T: SomeTrait>
应该紧跟在impl
关键字之后:
impl<T: SomeTrait> MyStruct<T> {
fn new(t: T) -> Self {
MyStruct { value: t }
}
}
Run Code Online (Sandbox Code Playgroud)
如果类型和约束的列表impl<...>
变得太长,您可以使用where
-syntax 并单独列出约束:
impl<T> MyStruct<T>
where
T: SomeTrait,
{
fn new(t: T) -> Self {
MyStruct { value: t }
}
}
Run Code Online (Sandbox Code Playgroud)
注意 的用法Self
,这是块MyStruct<T>
内部可用的快捷方式impl
。
评论
这个答案impl<T>
解释了为什么需要的原因。从本质上讲,它归结为一个事实,即和都是有效的,但意味着不同的东西。impl<T> MyStruct<T>
impl MyStruct<T>
当你new
进入impl
块时,你应该删除多余的类型参数,否则你的结构的接口将变得不可用,如下例所示:
// trait SomeTrait and struct MyStruct as above
// [...]
impl<T> MyStruct<T>
where
T: SomeTrait,
{
fn new<S: SomeTrait>(t: S) -> MyStruct<S> {
MyStruct { value: t }
}
}
impl SomeTrait for u64 {}
impl SomeTrait for u128 {}
fn main() {
// just a demo of problematic code, don't do this!
let a: MyStruct<u128> = MyStruct::<u64>::new::<u128>(1234);
// ^
// |
// This is an irrelevant type
// that cannot be inferred. Not only will the compiler
// force you to provide an irrelevant type, it will also
// not prevent you from passing incoherent junk as type
// argument, as this example demonstrates. This happens
// because `S` and `T` are completely unrelated.
}
Run Code Online (Sandbox Code Playgroud)