结构体具有通用特性,这个特性也是通用特性。

3
在Rust 1.15中,我创建了一个trait来抽象读取和解析文件格式。我正在尝试创建一个包含这个泛型trait的结构体。
这是我的trait:
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结构体?

好的,我道歉。刚推送评论后就注意到了。:x 你是否遵循了制作“PhantomData”的建议? - E net4
@E_net4 我不太确定怎么做? - Amandasaurus
https://dev59.com/ClkS5IYBdhLWcg3wCCXf#40487993 - E net4
2个回答

6
你可能不需要一个类型参数,而是想要一个关联类型:
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() {}

参见:


2
谢谢 - 那里有一些有见地的链接。 - Peter Hall

4
错误信息建议您使用标记,如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,但根据您的需求,它可能已经足够了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接