我想将一个函数包装在结构中以将其与其他数据打包在一起。当我明确指定函数的输入类型时,它可以正常工作。当我尝试将模式概括为通用结构时,会遇到生命周期错误。
我在操场上和下面共享了一个代码段。因为这是不能编译的。如果我从Wrapper
切换到WrapperExplicit
,则效果很好。怎么了我该如何使这种包装器具有通用性?
use std::marker::PhantomData;
struct Reference<'a, X> {
x : & 'a mut X
}
//Works
struct WrapperExplicit<F>
where F : Fn(Reference<String>)
{
data : u64,
func : F,
}
impl<F> WrapperExplicit<F>
where F : Fn(Reference<String>)
{
pub fn new(func: F) -> WrapperExplicit<F> {
WrapperExplicit {
data : 10,
func: func,
}
}
pub fn call(& mut self, arg: Reference<String>)
{
(self.func)(arg)
}
}
//Doesn't work
struct Wrapper<F, U>
where F : Fn(U)
{
data : u64,
func : F,
_marker: PhantomData<U>,
}
impl<F,U> Wrapper<F,U>
where F : Fn(U)
{
pub fn new(func: F) -> Wrapper<F,U> {
Wrapper {
data : 0,
func: func,
_marker: PhantomData {}
}
}
pub fn call(& mut self, arg: U)
{
(self.func)(arg)
}
}
fn fn_borrow(x : Reference<String>) {
println!("{}", x.x);
}
fn fn_move(y : String) {
println!("{}", &y);
}
pub fn test_example() {
let mut f = Wrapper::new(fn_borrow); //Doesn't work
// let mut f = WrapperExplicit::new(fn_borrow); //Works
let mut y = "Hello!".to_string();
let x = Reference{ x : &mut y};
f.call(x);
fn_move(y);
println!("{}", f.data)
}
编辑: 这是一个更简单的示例: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0f4f5236d4e4439b3bec5a717f62567c
我认为问题在于,因为在创建结构时必须设置泛型类型,所以还要设置泛型的生存期,因此在调用结构的关联对象时不能使用不同的生存期功能。真的吗?有没有一种方法可以让结构的“类型”部分具有通用性,而让寿命在结构的一个功能被调用时确定呢?
use std::marker::PhantomData;
//Doesn't work
struct WrapperSimple<U>
{
data : u64,
_marker: PhantomData<U>,
}
impl<U> WrapperSimple<U>
{
pub fn new() -> WrapperSimple<U> {
WrapperSimple {
data : 0,
_marker: PhantomData {}
}
}
pub fn call(& mut self, _arg: U)
{
}
pub fn call2<V>(& mut self, _arg: V)
{
}
}
fn fn_move(y : String) {
println!("{}", &y);
}
fn main() {
let mut w = WrapperSimple::<&str>::new();
let mut y = "Hello!".to_string();
let x = & mut y;
w.call(x); //Doesn't work
//w.call2(x); //Works, (obviously)
fn_move(y);
println!("{}", w.data)
}
编辑2:
我认为这是最终摆脱困境的方式:
因此,rust的类型系统当前不支持我要完成的操作。请让我知道我的假设之一是否错误。