为什么在将闭包作为特征对象参数传递时需要强制转换?
Why is a cast needed when a closure is passed as a trait object argument?
我正在尝试创建一个特征,该特征应该使用不同数量的参数对 functions/closures 进行抽象。像这样:
trait MyTrait {}
impl MyTrait for Box<Fn() -> &'static str> {}
impl MyTrait for Box<Fn(u8) -> u8> {}
最初我打算这样使用它:
fn myf<F: MyTrait>(_fun: F) {}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
但是此代码失败并出现错误:
error[E0277]: the trait bound `std::boxed::Box<[closure@src/main.rs:11:18: 11:31]>: MyTrait` is not satisfied
当我像这样投射盒子时,一切都正确编译:
myf(Box::new(|i: u8| i + 2) as Box<Fn(_) -> _>)
为什么 Rust 编译器不能在没有强制转换的情况下推断出这个特征?我的方法(使用 cast)是否正确,或者是否有更简单的方法?我更喜欢为我的项目启用 trivial_casts
警告,这个语法会触发它。
人们往往会忘记这一点:每个闭包都是实现 Fn
的不同结构:Fn
是一个特征,而不是结构,并且特征实现不是可传递的。
这里有一个小例子可以说明这一点:
trait Base {}
trait Derived {}
struct Foo {}
impl Base for Derived {}
impl Derived for Foo {}
fn myf<T>(_t: Box<T>)
where
T: Base + ?Sized,
{
}
fn main() {
let foo = Box::new(Foo {});
//myf(foo) // does not compile
myf(foo as Box<Derived>)
}
你真正想做的事情是:
trait MyTrait {}
impl<T> MyTrait for T
where
T: Fn() -> &'static str,
{
}
impl<T> MyTrait for T
where
T: Fn(u8) -> u8,
{
}
fn myf<F>(_fun: Box<F>)
where
F: MyTrait,
{
}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
但是这无法编译,因为有两个冲突的实现。
我正在尝试创建一个特征,该特征应该使用不同数量的参数对 functions/closures 进行抽象。像这样:
trait MyTrait {}
impl MyTrait for Box<Fn() -> &'static str> {}
impl MyTrait for Box<Fn(u8) -> u8> {}
最初我打算这样使用它:
fn myf<F: MyTrait>(_fun: F) {}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
但是此代码失败并出现错误:
error[E0277]: the trait bound `std::boxed::Box<[closure@src/main.rs:11:18: 11:31]>: MyTrait` is not satisfied
当我像这样投射盒子时,一切都正确编译:
myf(Box::new(|i: u8| i + 2) as Box<Fn(_) -> _>)
为什么 Rust 编译器不能在没有强制转换的情况下推断出这个特征?我的方法(使用 cast)是否正确,或者是否有更简单的方法?我更喜欢为我的项目启用 trivial_casts
警告,这个语法会触发它。
人们往往会忘记这一点:每个闭包都是实现 Fn
的不同结构:Fn
是一个特征,而不是结构,并且特征实现不是可传递的。
这里有一个小例子可以说明这一点:
trait Base {}
trait Derived {}
struct Foo {}
impl Base for Derived {}
impl Derived for Foo {}
fn myf<T>(_t: Box<T>)
where
T: Base + ?Sized,
{
}
fn main() {
let foo = Box::new(Foo {});
//myf(foo) // does not compile
myf(foo as Box<Derived>)
}
你真正想做的事情是:
trait MyTrait {}
impl<T> MyTrait for T
where
T: Fn() -> &'static str,
{
}
impl<T> MyTrait for T
where
T: Fn(u8) -> u8,
{
}
fn myf<F>(_fun: Box<F>)
where
F: MyTrait,
{
}
fn main() {
myf(Box::new(|i: u8| i + 2))
}
但是这无法编译,因为有两个冲突的实现。