简体   繁体   English

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

[英]How to implement non-generic trait on a struct with a generic parameter

I am using the I2CDevice trait which is defined in an external crate like this: 我正在使用这样的外部包装箱中定义的I2CDevice特性

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

Neither it nor any of its members contain any generic arguments. 它或其任何成员都不包含任何通用参数。

I am creating a decorator for any I2CDevice implementation which delegates to an inner/concrete I2CDevice , adding console printing for diagnostic purposes: 我正在为委派给内部/具体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.
}

I can't figure out what to put in place of __A__ and __B__ . 我不知道该用什么代替__A____B__

When I use no generic arguments whatsoever, I get compiler errors: Expected 1 lifetime parameter and Expected 1 type argument. 当我不使用任何通用参数时,会出现编译器错误: 预期的1个生存期参数预期的1个类型参数。

My best guess then is to leave __A__ blank because the definition of I2CDevice requires no generic arguments, and then to mirror the type argument used for the debugDeviceDecorator struct itself in place of __B__ like: 然后我最好的猜测是离开__A__空,因为定义I2CDevice不需要通用的参数,然后镜像用于类型参数debugDeviceDecorator结构本身代替__B__这样的:

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

I get the compilation error: error: expected one of ! 我收到编译错误: 错误:应该是其中之一! , ( , + , , , :: , < , or > , found : , which occurs on the colon ( : ) that begins the type constraint on the generic argument T . (+,::< ,或> ,实测值: ,这发生在冒号( : ),其开始于通用参数中的类型约束T

Perhaps the compiler thinks that I'm trying to constrain T in a manner which diverges from the constraint in the struct definition itself, so instead I try: 也许编译器认为我试图以与struct定义本身的约束不同的方式约束T ,所以我尝试:

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

Which results in the errors undeclared lifetime for the lifetime parameter, and undefined or not in scope for the type argument itself, at which point I cannot figure out how to proceed. 这导致生命周期参数的生存期未声明的错误,以及类型参数本身的作用域未定义的错误,这时我无法弄清楚如何进行。 I would assume that the lifetime and the type argument are defined by the future, as yet nonexistent code that will some day initialize a debugDeviceDecorator struct, values which cannot yet be known and seem to me as though should not prevent this existing code from compiling. 我会假设寿命和类型参数是由将来定义的,因为尚不存在的代码将在某天初始化debugDeviceDecorator结构,这些值尚不为人所知,在我看来似乎不应该阻止现有代码的编译。

I can see the compiler needing some information about the type of self.device used within the functions of the impl, but I feel like my first guess in which I mirrored the struct's expanded type definition in my impl declaration should have provided that. 我可以看到编译器需要一些有关在impl函数中使用的self.device类型的信息,但是我觉得我的第一个猜测是应该在我的impl声明中镜像该结构的扩展类型定义。

You should re-read The Rust Programming Language , specifically the section on how to implement traits for generic structs . 您应该重新阅读Rust编程语言 ,特别是有关如何实现通用结构特征的部分。 A lot of hard work has gone into that documentation so that people can get started in Rust easier. 该文档进行了许多艰苦的工作,以便人们可以更轻松地开始使用Rust。

The book will show you the proper syntax for how to define a trait for a struct: 本书将向您展示如何为结构定义特征的正确语法:

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

Note: 注意:

  1. You have to declare the two generic values ( 'a and T ) before you can use them. 您必须先声明两个通用值( 'aT ),然后才能使用它们。

  2. There's nothing special about the fact that the trait has no generics. 该特性没有泛型这一事实并没有什么特别的。

  3. Types in Rust use PascalCase , not camelCase , so I've changed the name. Rust中的类型使用PascalCase ,而不是camelCase ,因此我更改了名称。

  4. I switched to a where clause because it's too hard to read the bounds when they are crammed into the generic declaration. 我切换到where子句,因为当将边界塞入通用声明时,很难阅读它们的边界。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM