首页 文章

如何在具有泛型参数的结构上实现非泛型特征

提问于
浏览
1

我正在使用I2CDevice trait,它在外部包中定义,如下所示:

pub trait I2CDevice {
    type Error: Error;
    // members
}

它或它的任何成员都不包含任何通用参数 .

我正在为任何 I2CDevice 实现创建一个装饰器,它委托给内部/具体 I2CDevice ,添加控制台打印以用于诊断目的:

struct debugDeviceDecorator<'a, T: I2CDevice<Error = LinuxI2CError> + Sized + 'a> {
    device: &'a mut T,
}

impl I2CDevice__A__ for debugDeviceDecorator__B__ {
    type Error = LinuxI2CError;

    fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
        println!("read: data: {:?}", data);
        self.device.read(data)
    }

    // etc.
}

我无法弄清楚要放置什么 __A____B__ .

当我不使用任何泛型参数时,我得到编译器错误:预期的1个生命周期参数和预期的1个类型参数 .

我最好的猜测是将 __A__ 留空,因为 I2CDevice 的定义不需要泛型参数,然后镜像用于 debugDeviceDecorator 结构本身的类型参数代替 __B__ ,如:

impl I2CDevice for debugDeviceDecorator<'a, T: I2CDevice<Error=LinuxI2CError> + Sized + 'a> { }

我得到编译错误:错误:预期 !(+,::<> ,找到 : 之一,它出现在冒号( : )上,它开始对通用参数 T 进行类型约束 .

也许编译器认为我试图以一种与结构定义本身的约束不同的方式约束 T ,所以我尝试:

impl I2CDevice for debugDeviceDecorator<'a, T> {}

这导致生命周期参数的未声明生命周期的错误,未定义或不在类型参数本身的范围内,此时我无法弄清楚如何继续 . 我假设生命周期和类型参数是由未来定义的,但是不存在的代码有时会初始化一个 debugDeviceDecorator 结构,这些值在我看来是不可能的,好像不应该阻止这个现有的代码编译 .

我可以看到编译器需要一些关于impl函数中使用的 self.device 类型的信息,但我觉得我的第一个猜测是我在impl声明中镜像了struct的扩展类型定义应该提供的 .

1 回答

  • 5

    您应该重新阅读The Rust Programming Language,特别是how to implement traits for generic structs部分 . 这些文档已经付出了很多努力,以便人们可以更轻松地开始使用Rust .

    本书将向您展示如何为结构定义特征的正确语法:

    impl<'a, T> I2CDevice for DebugDeviceDecorator<'a, T>
        where T: I2CDevice<Error = LinuxI2CError> + Sized + 'a
    {
        // ...
    }
    

    注意:

    • 必须先声明两个通用值( 'aT )才能使用它们 .

    • 这个特性没有泛型这一事实并没有什么特别之处 .

    • Rust中的类型使用 PascalCase ,而不是 camelCase ,所以我更改了名称 .

    • 我切换到了一个 where 子句,因为当它们被塞入泛型声明时,读取边界太难了 .

相关问题