[英]Rust - clousures and generic types
To be honest, it's hard for me to describe the problem in words, so i'll show the code right away:老实说,我很难用语言来描述这个问题,所以我会马上展示代码:
// SomeType / SomeTrait
struct SomeType;
trait SomeTrait {
fn do_sth() -> &'static str;
}
impl SomeTrait for SomeType {
fn do_sth() -> &'static str {
"do_sth()"
}
}
// SomeOtherType / SomeOtherTrait
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C>(&self, c: C)
where
C: Fn(SomeType), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(SomeType);
}
}
trait SomeOtherTrait {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait for SomeOtherType {
fn perform_sth<C, D>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str,
{
self.get_some_trait(|arg: SomeType| {
c(&arg); // <- Problem
// Error: expected type parameter `D`, found struct `SomeType`
// But `D: SomeTrait` and SomeType implements `SomeTrait`
});
}
}
fn main() {}
The code above is a simplified model of the situation I find myself in.上面的代码是我发现自己所处情况的简化 model。
If i have |arg: SomeType|
如果我有
|arg: SomeType|
, the c
clousure takes reference to generic type T
, that implements SomeType
- why can't i pass arg
as argument for c
? ,
c
clousure 引用了泛型类型T
,它实现SomeType
- 为什么我不能将arg
作为c
的参数传递?
Thank you in advance for your help in solving the problem.预先感谢您帮助解决问题。 I apologise for any mistakes in my English.
对于我的英语中的任何错误,我深表歉意。
I don't think your current definition of SomeOtherTrait
allows this since it leaves filling in the D
parameter to the caller by defining it on perform_sth
but you internally already bind it to be SomeType
by virtue of SomeOtherType::get_some_trait
.我不认为您当前对
SomeOtherTrait
的定义允许这样做,因为它通过在perform_sth
上定义它来将D
参数填充给调用者,但是您在内部已经通过SomeOtherType::get_some_trait
SomeType
其绑定为 SomeType 。
If you introduce a generic parameter D
on SomeOtherTrait
, you can bind D
in a given type's implementation of SomeOtherTrait
to whatever it requires:如果您在
SomeOtherTrait
上引入泛型参数D
,则可以将D
在给定类型的SomeOtherTrait
实现中绑定到所需的任何内容:
trait SomeOtherTrait<D> {
fn perform_sth<C>(&self, c: C)
where
D: SomeTrait,
C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}
impl SomeOtherTrait<SomeType> for SomeOtherType {
fn perform_sth<C>(&self, c: C)
where
C: Fn(&SomeType) -> &'static str,
{
self.get_some_trait(|arg| {
c(&arg);
});
}
}
The other option is adjusting get_some_trait
to be generic over the argument to c
, although you'll then need to be able to construct it, eg through D::Default()
:另一个选项是将
get_some_trait
调整为对c
的参数通用,尽管您随后需要能够构造它,例如通过D::Default()
:
// ...
struct SomeOtherType;
impl SomeOtherType {
fn get_some_trait<C, D>(&self, c: C)
where
D: Default,
C: Fn(D), // Takes clousure, clousure have to get `SomeType`-type paramm
{
c(D::default());
}
}
// ...
which in turn entails adding the D: Default
bound to SomeOtherTrait::perform_sth
.这反过来又需要添加
D: Default
绑定到SomeOtherTrait::perform_sth
。
The issue is that this will only work if D
is SomeType
.问题是这只有在
D
是SomeType
。 Say for example I have the code bellow:比如说我有下面的代码:
struct Foo;
impl SomeTrait for Foo {
fn do_sth() -> &'static str {
"Foo"
}
}
SomeOtherType.perform_sth::<_, Foo>(|_: &Foo| "Bla" );
This code is completely valid, but the current implementation of perform_sth
attempts to use SomeType
despite my closure expecting Foo
should be used instead.此代码完全有效,但
perform_sth
的当前实现尝试使用SomeType
尽管我的闭包期望Foo
应该改用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.