generics - 难以理解 Rust 中的特征和泛型

标签 generics rust traits

我对尝试编写泛型非常陌生,而且 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) {}
}

我在其中尝试定义一个特征,在几个结构上实现该特征,然后有一个函数返回这些结构之一。这可能吗?

我得到编译器错误:

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意味着该函数返回 M ,这是一些(不是任何)Mapper .泛型由调用者提供(显式使用 choose_mapper::<SomeM>(foo) 或大部分时间从上下文推断,如 let bar: SomeM = choose_mapper(foo) )。

您的函数试图返回 Mapper1 (这是一些 M ,但不一定与调用者想要的相同)。

您应该将签名更改为

pub fn choose_mapper(rom_header: &RomHeader) -> Box<Mapper>;

它允许函数选择它返回的内容。

有趣的是 a very active RFC这将允许函数选择它返回的内容(通常称为 impl Trait ,尽管尚未选择语法)。

关于generics - 难以理解 Rust 中的特征和泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38164344/

相关文章:

rust - 引用 Rust 中 impl block 中的特征

java泛型返回一个数组

C# 如何创建一个调用另一个泛型方法的委托(delegate)的方法

PHP Trait 覆盖 protected Trait 方法

rust - FromStr 特征不暴露生命周期的原因是什么?

pointers - 通过多个 "as"转换如何转换原始 str ?

java - 自定义迭代器返回对象

java - 无类型的列表实现

rust - SFML 中的生命周期说明符和泛型

generics - 如何通过抽象将使用 Diesel 的多个功能合并为一个?