Generics 如何指定通过move传递给函数的泛型类型的生存期?

Generics 如何指定通过move传递给函数的泛型类型的生存期?,generics,rust,lifetime,Generics,Rust,Lifetime,我想将一个函数包装在一个结构中,以便将其与其他数据打包。当我显式地指定函数的输入类型时,它工作得很好。当我尝试将模式概括为泛型结构时,我会遇到生存期错误 我在操场和下面分享了一段代码片段。照原样,这是不可编译的。如果我从Wrapper切换到WrapperExplicit,它工作得非常好。怎么了?如何使这个包装器通用 使用std::marker::PhantomData; 结构引用包装器{ 包装器{ 数据:10, func:func, } } 发布fn调用(&mut self,arg:Refer

我想将一个函数包装在一个结构中,以便将其与其他数据打包。当我显式地指定函数的输入类型时,它工作得很好。当我尝试将模式概括为泛型结构时,我会遇到生存期错误

我在操场和下面分享了一段代码片段。照原样,这是不可编译的。如果我从
Wrapper
切换到
WrapperExplicit
,它工作得非常好。怎么了?如何使这个包装器通用

使用std::marker::PhantomData;
结构引用包装器{
包装器{
数据:10,
func:func,
}
}
发布fn调用(&mut self,arg:Reference)
{
(自我功能)(arg)
}
}
//不起作用
结构包装器
式中F:Fn(U)
{
数据:u64,
func:F,
_标记:幻影数据,
}
impl包装器
式中F:Fn(U)
{
pub fn new(func:F)->包装器{
包装纸{
数据:0,
func:func,
_标记:幻影数据{}
}
}
发布fn调用(&mut self,arg:U)
{
(自我功能)(arg)
}
}
fn fn_借用(x:参考){
println!(“{}”,x.x);
}
fn fn_移动(y:字符串){
println!({},&y);
}
pub fn test_example(){
让mut f=Wrapper::new(fn_borrow);//不起作用
//让mut f=wrappexplicit::new(fn_borrow);//有效
让mut y=“Hello!”.to_string();
设x=Reference{x:&mut y};
f、 呼叫(x);
fn_移动(y);
println!(“{}”,f.data)
}

编辑: 这里有一个更简单的例子:

我认为问题在于,因为在创建结构时必须设置泛型类型,所以泛型类型的生存期也会随之设置,所以在调用结构的关联函数时不能使用不同的生存期。这是真的吗?有没有一种方法可以让结构的“类型”部分是泛型的,但让生命周期在调用结构的某个函数时决定

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)
}
使用std::marker::PhantomData;
//不起作用
结构包装器简单
{
数据:u64,
_标记:幻影数据,
}
简单包装器
{
pub fn new()->WrapperSimple{
包装简单{
数据:0,
_标记:幻影数据{}
}
}
发布fn调用(&mut self,_arg:U)
{
}
发布fn调用2(&mut self,_arg:V)
{
}
}
fn fn_移动(y:字符串){
println!({},&y);
}
fn main(){
让mut w=WrapperSimple:::new();
让mut y=“Hello!”.to_string();
设x=&mut y;
w、 调用(x);//不起作用
//w、 call2(x);//显然有效
fn_移动(y);
println!(“{}”,w.data)
}

编辑2:

我认为这是它最终如何摆脱的:

  • 不能在结构中存储带有泛型输入的泛型函数 在结构的类型中不引用函数的输入类型 参数,因此还需要该类型的PhantomData字段 (否则,您有一个不受约束或未使用的类型参数)
  • 一旦您有了该类型的字段,该类型的嵌入生存期就结束了 当结构为单晶时设置,例如在 建筑
  • 这意味着生命周期是固定的,不能随时间变化 当您调用结构的一个方法时
  • 您也不能为方法创建新的泛型类型参数并将其约束为与结构的类型参数匹配,除非剥离结构类型的生存期

因此,rust的类型系统目前不支持我想要实现的功能。如果我在这里的假设有误,请告诉我。

这似乎需要更高级的类型来正确表达这一点,而Rust还不支持这一点。通常会有一些解决方法,但在这种情况下,我想不出一个简单的方法。如果您能以某种方式将
call
的参数类型改为
&mut U
,而不是
U
,这就行了。谢谢你看,斯文。我认为更高种类的类型可能是一种方法,但如果有一种方法将泛型类型与其他类型而不是特征绑定在一起,您也可以让它起作用。换句话说,类似于
pub fn call(&'a mut self,_arg:V),其中V:U+'b{}
其中
U+'b
表示与
U
相同的类型,但是使用类型的生存期
'b
,而不是最初绑定到U的任何生存期。不幸的是,您的示例只起作用,因为U没有任何嵌入引用,因此没有关联的生存期,即您所称的生存期。如果将
str
替换为
&str
,则它再次不起作用。
U+'b
语法将是不明确的,因为
U
可以由不同嵌套级别的任意数量的生存期参数来参数化,并且不清楚
'b
约束的生存期是什么。此外,泛型类型的生存期界限
'b
意味着该类型至少在该生存期内有效。您需要缩短此处的生命周期来解决冲突,因此无论如何这都不是一个解决方案。
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)
}