具有通用特征的结构也是通用特征
Struct with a generic trait which is also a generic trait
在 Rust 1.15 中,我创建了一个特征来抽象读取和解析文件格式。我正在尝试创建一个内部具有此通用特征的结构。
我有这个特质:
use std::io::Read;
trait MyReader<R: Read> {
fn new(R) -> Self;
fn into_inner(self) -> R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
我想创建一个结构,它引用了实现它的东西。
struct MyIterThing<'a, T: MyReader<R>+'a> {
inner: &'a mut T,
}
出现以下错误:
error[E0412]: type name `R` is undefined or not in scope
--> <anon>:11:36
|
11 | struct MyIterThing<'a, T: MyReader<R>+'a> {
| ^ undefined or not in scope
|
= help: no candidates by the name of `R` found in your project; maybe you misspelled the name or forgot to import an external crate?
T: MyReader+'a
,我得到错误:"error[E0243]: wrong number of type arguments: expected 1, found 0"
,T: MyReader<R: Read>+'a
给出了一个低级语法错误,它不期望那里有 :
。
这也行不通:
error[E0392]: parameter `R` is never used
--> <anon>:11:24
|
11 | struct MyIterThing<'a, R: Read, T: MyReader<R>+'a> {
| ^ unused type parameter
|
= help: consider removing `R` or using a marker such as `std::marker::PhantomData`
如何创建我的 MyIterThing
结构?
错误消息建议您使用标记,例如 PhantomData。你可以这样做:
use std::marker::PhantomData;
struct MyIterThing<'a, R: Read, T: MyReader<R> + 'a> {
inner: &'a mut T,
marker: PhantomData<R>,
}
PhantomData
的实例的运行时成本为零,因此使用它比仅创建类型 R
.
的字段更好
另一个解决方案是使用关联类型而不是类型参数:
trait MyReader {
type Source: Read;
fn new(Self::Source) -> Self;
fn into_inner(self) -> Self::Source;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
struct MyIterThing<'a, T: MyReader + 'a> {
inner: &'a mut T,
}
这有点不够灵活,因为每个 MyReader
的实现只能选择一个 Source
,但这可能就足够了,具体取决于您的需要。
您可能不需要类型参数,您需要一个关联类型:
use std::io::Read;
trait MyReader {
type R: Read;
fn new(Self::R) -> Self;
fn into_inner(self) -> Self::R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
struct MyIterThing<'a, T>
where T: MyReader + 'a
{
inner: &'a mut T,
}
fn main() {}
另请参阅:
在 Rust 1.15 中,我创建了一个特征来抽象读取和解析文件格式。我正在尝试创建一个内部具有此通用特征的结构。
我有这个特质:
use std::io::Read;
trait MyReader<R: Read> {
fn new(R) -> Self;
fn into_inner(self) -> R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
我想创建一个结构,它引用了实现它的东西。
struct MyIterThing<'a, T: MyReader<R>+'a> {
inner: &'a mut T,
}
出现以下错误:
error[E0412]: type name `R` is undefined or not in scope
--> <anon>:11:36
|
11 | struct MyIterThing<'a, T: MyReader<R>+'a> {
| ^ undefined or not in scope
|
= help: no candidates by the name of `R` found in your project; maybe you misspelled the name or forgot to import an external crate?
T: MyReader+'a
,我得到错误:"error[E0243]: wrong number of type arguments: expected 1, found 0"
,T: MyReader<R: Read>+'a
给出了一个低级语法错误,它不期望那里有 :
。
这也行不通:
error[E0392]: parameter `R` is never used
--> <anon>:11:24
|
11 | struct MyIterThing<'a, R: Read, T: MyReader<R>+'a> {
| ^ unused type parameter
|
= help: consider removing `R` or using a marker such as `std::marker::PhantomData`
如何创建我的 MyIterThing
结构?
错误消息建议您使用标记,例如 PhantomData。你可以这样做:
use std::marker::PhantomData;
struct MyIterThing<'a, R: Read, T: MyReader<R> + 'a> {
inner: &'a mut T,
marker: PhantomData<R>,
}
PhantomData
的实例的运行时成本为零,因此使用它比仅创建类型 R
.
另一个解决方案是使用关联类型而不是类型参数:
trait MyReader {
type Source: Read;
fn new(Self::Source) -> Self;
fn into_inner(self) -> Self::Source;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
struct MyIterThing<'a, T: MyReader + 'a> {
inner: &'a mut T,
}
这有点不够灵活,因为每个 MyReader
的实现只能选择一个 Source
,但这可能就足够了,具体取决于您的需要。
您可能不需要类型参数,您需要一个关联类型:
use std::io::Read;
trait MyReader {
type R: Read;
fn new(Self::R) -> Self;
fn into_inner(self) -> Self::R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
struct MyIterThing<'a, T>
where T: MyReader + 'a
{
inner: &'a mut T,
}
fn main() {}
另请参阅: