我有一个包含函数对象的 struct :
struct Foo<F> {
func: F,
}
我想在 struct 定义中添加一个Fn
trait绑定.问题是:我确实关心第一个参数(必须是i32
),但不关心第二个参数.我真正想写的是这样的:
struct Foo<F>
where
∃ P so that F: Fn(i32, P),
{
func: F,
}
所以在英语中,类型F
必须是一个接受两个参数的函数,第一个参数是i32
(第二个参数可以是任何参数).上述语法显然无效.我想到了三种可能的解决方案:
for<>
语法在这里没有帮助.除此之外,它还不适用于非生命参数,它是通用的("所有")而不是存在的("存在").这就结束了.-
另一种可能是向 struct 添加类型参数.我已经不喜欢这个解决方案了,因为参数本身并不属于 struct .
struct Foo<F, P> where F: Fn(i32, P), { func: F, }
但这不起作用:参数
P
没有被使用,除非在where
绑定中,所以编译器会抱怨.这个问题可以通过添加
PhantomData<P>
字段来解决,但这不应该是必要的,更重要的是,用户不能再轻易地使用struct构造函数语法了. -
最后我试了一下:
struct Foo<F> where F: Fn(i32, _), { func: F, }
但这也不起作用:
error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> src/main.rs:3:20 | 3 | F: Fn(i32, _), | ^ not allowed in type signatures
Is there a way to achieve what I want?
Side note:为什么我想把trait绑定到struct上,而不是仅仅绑定到重要的impl
个块上?
首先,一旦实现了"隐含特征边界"RFC,这就允许我从所有impl
个块中省略重复的特征边界.其次,有了这个界限,它可以帮助编译器进行类型推断.考虑一下:
struct Foo<F, T>
where
F: Fn(T, _),
{
data: T,
F: F,
}
如果边界是可能的(我用上面的PhantomData
个"解决方案"进行了try ),编译器可以更容易地推断闭包的第一个参数的类型.如果只在impl块上指定trait界限,编译器就会遇到困难.