有没有表达“相同”的泛型类型具有不同的生命周期约束的方法吗?

问题描述 投票:2回答:1

考虑以下(不完全)的函数签名:

unsafe fn foo<'a, T: 'a>(func: impl FnOnce() -> T + 'a) -> ...

有一种方法,以(不安全的路线)transmute输入功能,从而,它成为impl FnOnce() -> S + 'static其中S是相同的类型为T而与S: 'static

我知道这是可能通过使用盒装特质(FnBox),然后调用蜕变包装盒上的蜕变在封闭本身的寿命范围。然而,这并不影响返回类型(T)。据我了解,T: 'aT: 'static不同类型尽可能的类型系统进入。所以我想如果它甚至有可能在拉斯特来表达这一点。

我想签名必须看起来像这样(忽略在封闭本身的寿命范围):

unsafe fn<'a, T, S>(func: impl FnOnce() -> T) -> impl FnOnce() -> S
where
    T: 'a,
    S: 'static`

但后来你怎么骂不说T规范这个功能和S是,除了他们的一生必然是相同的。

免责声明我知道终身界限摆弄通常是一个坏主意,但是这对于寿命限制通过其他手段强制产卵线程。

generics rust lifetime type-constraints
1个回答
2
投票

如果你只是想用简单的类型要做到这一点,这将是简单的,但也有一些障碍,你想什么。我将解释他们的顺序,我碰到他们试图找到答案。

首先,你不能impl trait类型实现这一点,因为函数本身必须选择具体的实现,这是怎么回事返回,但不能因为实施将始终基于从类型参数func的选择呼叫者,召集者。这排除了“自然”的类型:

unsafe fn foo<'a, T>(func: impl FnOnce() -> T + 'a) -> impl FnOnce() -> T + 'static

并导致更多的东西,如:

unsafe fn foo<'a, T, F, G>(func: F) -> G
where
    F: FnOnce() -> + 'a,
    G: FnOnce() -> + 'static,

但是,如何调用者知道什么类型的G需要呢?

如果您尝试使用mem::transmute骗借检查,你需要告诉它什么蜕变成。问题是,你只知道类型是(例如)impl FnOnce() -> T + 'static,但你不能真正写下具体类型封闭,所以这是不会工作的。

因此,我认为答案是Box结果。这听起来似乎不尽人意,但它变得更糟糕!虽然它可以创建一个Box<dyn FnOnce()>currently impossible to call that function later,这意味着你必须做出妥协另一个,这是从FnOnce升级到Fn

use std::mem;

unsafe fn foo<'a, T>(func: impl Fn() -> T + 'a) -> Box<dyn Fn() -> T + 'static> {
    let boxed: Box<dyn Fn() -> T + 'a> = Box::new(func);
    mem::transmute(boxed)
}

综上所述,也许你应该退后一步,并找到一个不同的问题来解决,而不是这一个。

© www.soinside.com 2019 - 2024. All rights reserved.