如何在具有泛型参数的结构上实现非泛型特征 [英] How to implement non-generic trait on a struct with a generic parameter
问题描述
我正在使用 I2CDevice
特质在外部包装箱中定义,如下所示:
I am using the I2CDevice
trait which is defined in an external crate like this:
pub trait I2CDevice {
type Error: Error;
// members
}
它或其任何成员都不包含任何通用参数.
Neither it nor any of its members contain any generic arguments.
我正在为任何 I2CDevice
实现创建装饰器,该装饰器委派给内部/具体的 I2CDevice
,并添加控制台打印以用于诊断目的:
I am creating a decorator for any I2CDevice
implementation which delegates to an inner/concrete I2CDevice
, adding console printing for diagnostic purposes:
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 __
.
I can't figure out what to put in place of __A__
and __B__
.
当我不使用任何泛型参数时,会出现编译器错误:预期的1个生存期参数和预期的1个类型参数.
When I use no generic arguments whatsoever, I get compiler errors: Expected 1 lifetime parameter and Expected 1 type argument.
然后我的最佳猜测是将 __ A __
留空,因为 I2CDevice
的定义不需要通用参数,然后镜像用于 debugDeviceDecorator的类型参数
结构本身代替 __ B __
,例如:
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:
impl I2CDevice for debugDeviceDecorator<'a, T: I2CDevice<Error=LinuxI2CError> + Sized + 'a> { }
我收到编译错误:错误:预期为!
,(
, +
,,
, ::
,<
或>
,发现:
在冒号(:
)上,该冒号开始对通用参数 T
施加类型约束.
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:
impl I2CDevice for debugDeviceDecorator<'a, T> {}
这将导致生命周期参数错误未声明的生命周期,而类型参数本身出现未定义范围的错误,此时我无法弄清楚如何继续.我假设寿命和类型参数是由将来定义的,因为尚不存在的代码将在某天初始化 debugDeviceDecorator
结构,这些值尚不为人所知,在我看来似乎不应该阻止此现有代码进行编译.
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.
我可以看到编译器需要一些有关在impl函数中使用的 self.device
类型的信息,但是我觉得这是我的第一次猜测,在其中我镜像了该结构的扩展类型定义.我的隐含声明应该已经提供了.
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.
推荐答案
You should re-read The Rust Programming Language, specifically the section on how to implement traits for generic structs. A lot of hard work has gone into that documentation so that people can get started in Rust easier.
这本书将向您展示如何为结构定义特征的正确语法:
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
{
// ...
}
注意:
-
在使用它们之前,必须声明两个通用值(
'a
和T
).
该特征没有泛型这一事实没什么特别的.
There's nothing special about the fact that the trait has no generics.
Rust中的类型使用 PascalCase
,而不是 camelCase
,所以我更改了名称.
Types in Rust use PascalCase
, not camelCase
, so I've changed the name.
我切换到了 where
子句,因为当将边界塞入通用声明时很难读取边界.
I switched to a where
clause because it's too hard to read the bounds when they are crammed into the generic declaration.
这篇关于如何在具有泛型参数的结构上实现非泛型特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!