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

时间:2017-03-11 22:49:46

标签: generics rust

我使用的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> { }

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

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

T

哪个导致生命周期参数的错误未声明的生命周期,并且未定义或未在范围中为类型参数本身,此时我无法弄清楚如何继续。我假设生命周期和类型参数是由未来定义的,但是不存在的代码有时会初始化impl I2CDevice for debugDeviceDecorator<'a, T> {} 结构,这些值在我看来是不可能的,并且在我看来似乎不应该阻止现有的来自编译的代码。

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

1 个答案:

答案 0 :(得分: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
{
    // ...
}

注意:

  1. 您必须先声明两个通用值('aT),然后才能使用它们。

  2. 特质没有仿制品这一事实并不特别。

  3. Rust中的类型使用PascalCase,而非camelCase,因此我更改了名称。

  4. 我切换到where条款,因为当它们被塞进通用声明时,它很难读取界限。