难以理解 Rust 中的特征和泛型
Having trouble understanding traits and generics in Rust
我对尝试编写泛型非常陌生,而且 Rust 的特性一直让我难以理解。我有这段代码:
pub trait Mapper {
fn prg_rom_read(&self, addr: u16) -> u8 {}
fn prg_rom_write(&mut self, addr: u16, val: u8) {}
fn chr_rom_read(&self, addr: u16) -> u8 {}
fn chr_rom_write(&mut self, addr: u16, val: u8) {}
}
pub fn choose_mapper<M: Mapper>(rom_header: &RomHeader) -> M {
match rom_header.mapper_number {
0 => Mapper1::new(rom_header),
_ => panic!("Unsupported mapper: {:#}", rom_header.mapper_number),
}
}
struct Mapper1 {
prg_ram: Box<[u8]>,
prg_rom: Box<[u8]>,
chr: Box<[u8]>,
}
impl Mapper1 {
pub fn new(rom_header: &RomHeader) -> Self {
Mapper1 {
prg_ram: {
let size = rom_header.prg_ram_size as usize * 8192;
vec![0; size].into_boxed_slice()
},
prg_rom: {
let size = rom_header.prg_rom_size as usize * 16384;
vec![0; size].into_boxed_slice()
},
chr: {
let size = rom_header.chr_rom_size as usize * 8192;
vec![0; size].into_boxed_slice()
},
}
}
}
impl Mapper for Mapper1 {
fn prg_rom_read(&self, addr: u16) -> u8 {}
fn prg_rom_write(&mut self, addr: u16, val: u8) {}
fn chr_rom_read(&self, addr: u16) -> u8 {}
fn chr_rom_write(&mut self, addr: u16, val: u8) {}
}
我在其中尝试定义一个特征,在多个结构上实现该特征,然后具有一个函数,其中 returns 这些结构之一。这甚至可能吗?
我收到编译器错误:
expected `_`,
found `mapper::Mapper1`
(expected type parameter,
found struct `mapper::Mapper1`) [E0308]
src/mapper.rs:11 match rom_header.mapper_number {
src/mapper.rs:12 0 => Mapper1::new(rom_header),
src/mapper.rs:13 _ => panic!("Unsupported mapper: {:#}", rom_header.mapper_number),
src/mapper.rs:14 }
src/mapper.rs:11:5: 14:6 help: run `rustc --explain E0308` to see a detailed explanation
src/mapper.rs:12:14: 12:38 note: match arm with an incompatible type
src/mapper.rs:12 0 => Mapper1::new(rom_header),
^~~~~~~~~~~~~~~~~~~~~~~~
pub fn choose_mapper<M: Mapper>(rom_header: &RomHeader) -> M
表示函数 returns M
,它是一些(不是任何)Mapper
。泛型由调用者 提供 (明确地使用 choose_mapper::<SomeM>(foo)
或大部分时间从上下文推断,如 let bar: SomeM = choose_mapper(foo)
)。
您的函数尝试 return 一个 Mapper1
(这是一些 M
,但不一定与调用者想要的相同)。
您应该将签名更改为
pub fn choose_mapper(rom_header: &RomHeader) -> Box<Mapper>;
它允许函数选择它 returns.
有趣的是 a very active RFC 允许函数选择它 return 的内容(通常称为 impl Trait
,尽管尚未选择语法)。
我对尝试编写泛型非常陌生,而且 Rust 的特性一直让我难以理解。我有这段代码:
pub trait Mapper {
fn prg_rom_read(&self, addr: u16) -> u8 {}
fn prg_rom_write(&mut self, addr: u16, val: u8) {}
fn chr_rom_read(&self, addr: u16) -> u8 {}
fn chr_rom_write(&mut self, addr: u16, val: u8) {}
}
pub fn choose_mapper<M: Mapper>(rom_header: &RomHeader) -> M {
match rom_header.mapper_number {
0 => Mapper1::new(rom_header),
_ => panic!("Unsupported mapper: {:#}", rom_header.mapper_number),
}
}
struct Mapper1 {
prg_ram: Box<[u8]>,
prg_rom: Box<[u8]>,
chr: Box<[u8]>,
}
impl Mapper1 {
pub fn new(rom_header: &RomHeader) -> Self {
Mapper1 {
prg_ram: {
let size = rom_header.prg_ram_size as usize * 8192;
vec![0; size].into_boxed_slice()
},
prg_rom: {
let size = rom_header.prg_rom_size as usize * 16384;
vec![0; size].into_boxed_slice()
},
chr: {
let size = rom_header.chr_rom_size as usize * 8192;
vec![0; size].into_boxed_slice()
},
}
}
}
impl Mapper for Mapper1 {
fn prg_rom_read(&self, addr: u16) -> u8 {}
fn prg_rom_write(&mut self, addr: u16, val: u8) {}
fn chr_rom_read(&self, addr: u16) -> u8 {}
fn chr_rom_write(&mut self, addr: u16, val: u8) {}
}
我在其中尝试定义一个特征,在多个结构上实现该特征,然后具有一个函数,其中 returns 这些结构之一。这甚至可能吗?
我收到编译器错误:
expected `_`,
found `mapper::Mapper1`
(expected type parameter,
found struct `mapper::Mapper1`) [E0308]
src/mapper.rs:11 match rom_header.mapper_number {
src/mapper.rs:12 0 => Mapper1::new(rom_header),
src/mapper.rs:13 _ => panic!("Unsupported mapper: {:#}", rom_header.mapper_number),
src/mapper.rs:14 }
src/mapper.rs:11:5: 14:6 help: run `rustc --explain E0308` to see a detailed explanation
src/mapper.rs:12:14: 12:38 note: match arm with an incompatible type
src/mapper.rs:12 0 => Mapper1::new(rom_header),
^~~~~~~~~~~~~~~~~~~~~~~~
pub fn choose_mapper<M: Mapper>(rom_header: &RomHeader) -> M
表示函数 returns M
,它是一些(不是任何)Mapper
。泛型由调用者 提供 (明确地使用 choose_mapper::<SomeM>(foo)
或大部分时间从上下文推断,如 let bar: SomeM = choose_mapper(foo)
)。
您的函数尝试 return 一个 Mapper1
(这是一些 M
,但不一定与调用者想要的相同)。
您应该将签名更改为
pub fn choose_mapper(rom_header: &RomHeader) -> Box<Mapper>;
它允许函数选择它 returns.
有趣的是 a very active RFC 允许函数选择它 return 的内容(通常称为 impl Trait
,尽管尚未选择语法)。