generics - 有没有办法用不同的生命周期来表达“相同”的泛型类型?
问题描述
考虑以下(不完整的)函数签名:
unsafe fn foo<'a, T: 'a>(func: impl FnOnce() -> T + 'a) -> ...
有没有办法(当然不安全)transmute
输入函数,使它成为impl FnOnce() -> S + 'static
S 与 T 相同类型但带有S: 'static
.
我知道可以通过使用盒装特征 ( FnBox
) 然后在盒子上调用 transmute 来改变闭包本身的生命周期边界。但是,这不会影响返回类型 ( T
)。据我了解,就类型系统而言,它们是不同的类型T: 'a
。T: 'static
所以我想知道是否甚至可以用 Rust 来表达这一点。
我想签名必须看起来像这样(忽略闭包本身的生命周期边界):
unsafe fn<'a, T, S>(func: impl FnOnce() -> T) -> impl FnOnce() -> S
where
T: 'a,
S: 'static`
但是你如何在没有规范的情况下调用这个函数,T
并且S
除了它们的生命周期限制之外是相同的。
免责声明 我知道修改生命周期界限通常是一个坏主意,但是这是用于生成通过其他方式强制执行生命周期限制的线程。
解决方案
如果你只是想用简单的类型来做这件事,这很简单,但是你正在尝试的东西有很多障碍。我将按照我在试图找到答案时遇到的顺序来解释它们。
首先,你不能用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()>
但目前无法稍后调用该函数,这意味着您必须做出另一个妥协,即从 升级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)
}
总之,也许你应该退后一步,找到一个不同的问题来解决,而不是这个。
推荐阅读
- mysql - 无法在 mysql 工作台中运行 sql 脚本
- powershell - Get-ADUser 上的错误?
- vba - Web Scraping - 从 Searates 网站到 Excel 的容器跟踪
- python - BlockingIOError:[Errno 11]资源暂时不可用两个客户端一个服务器套接字python
- typescript - 如何在打字稿对象中使用自引用?
- qt - QML 设置字体大小写
- python - Statsmodels OLS 公式中的数据帧计数
- installation - v8 没有安装日志
- javascript - javascript - toFixed (444.2).toFixed(14) 中的隐蔽问题
- vnc-server - 使用tigervnc通过XDMCP访问centos7.8,键盘事件失效