![](/img/trans.png)
[英]How to convert a generic function into a function pointer with a reference parameter?
[英]Generic parameter with reference used as function pointer argument
我无法弄清楚哪个生命周期参数对此有效,因此我当前的解决方法包括转换或原始指针。 我有一个结构包含一个函数指针,以泛型为参数:
struct CB<Data> {
cb: fn(Data) -> usize
}
我想存储一个实例,由包含引用的某种类型参数化,存储在一些其他结构中,该结构使用一种方法实现特征,并使用该特征方法调用 CB 中的函数指针。
struct Holder<'a> {
c: CB<Option<&'a usize>>
}
trait Exec {
fn exec(&self, v: &usize) -> usize;
}
impl<'a> Holder<'a> {
fn exec_aux(&self, v: &'a usize) -> usize {
(self.c.cb)(Some(v))
}
}
impl<'a> Exec for Holder<'a> {
fn exec(&self, v: &usize) -> usize
{
self.exec_aux(v)
}
}
对于 Holder 的“Exec”实现,这给了我一个终生错误:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
只要我不定义Exec
impl,简单地调用exec_aux
可以正常工作:
fn main() {
let h = Holder { c: CB{cb:cbf}};
let v = 12;
println!("{}", h.exec_aux(&v));
}
此外,使 CB 不通用也使这项工作:
struct CB {
cb: fn(Option<&usize>) -> usize
}
我的实际代码中的参数不是使用usize
而是我不想复制的大参数。
你的Exec
trait 中的生命周期是这样的:
trait Exec {
fn exec<'s, 'a>(&'s self, v: &'a usize) -> usize;
}
换句话说,实现Exec
类型需要接受任何生命周期's
和'a
。 但是,您的Holder::exec_aux
方法需要一个特定的生命周期'a
,它与Holder
类型的生命周期参数相关联。
要使其工作,您需要将'a
作为生命周期参数添加到Exec
特征,以便您可以专门为该生命周期实现特征:
trait Exec<'a> {
// ^^^^ vv
fn exec(&self, v: &'a usize) -> usize;
}
impl<'a> Exec<'a> for Holder<'a> {
// ^^^^ vv
fn exec(&self, v: &'a usize) -> usize
{
self.exec_aux(v)
}
}
这里的问题是Exec
trait 太通用了,不能被Holder
以这种方式使用。 首先,考虑定义:
trait Exec {
fn exec(&self, v: &usize) -> usize;
}
此定义将导致编译器自动为exec
&self
和&v
分配两个匿名生命周期。 它基本上与
fn exec<'a, 'b>(&'a self, v: &'b usize) -> usize;
请注意,对于谁需要比谁存活时间长没有限制,引用只需要在方法调用期间保持存活即可。
现在考虑定义
impl<'a> Holder<'a> {
fn exec_aux(&self, v: &'a usize) -> usize {
// ... doesn't matter
}
}
既然我们知道&self
是一个&Holder<'a>
(这就是impl
所指的),我们这里至少需要有一个&'a Holder<'a>
,因为&'_ self
不能有生命周期比Holder<'a>
'a
短。 所以这就是说这两个参数具有相同的生命周期: &'a self, &'a usize
。
当您尝试将两者结合起来时,一切都会出错。 该特征迫使您进入以下签名,该签名(再次)具有两个不同的隐式生命周期。 但是,您随后尝试对其调用方法的实际Holder
迫使您对&self
和&v
具有相同的生命周期。
fn exec(&self, v: &usize) -> usize {
// Holder<'a> needs `v` to be `'a` when calling exec_aux
// But the trait doesn't say so.
self.exec_aux(v)
}
一种解决方案是将特征重新定义为
trait Exec<'a> {
fn exec(&'a self, v: &'a usize) -> usize;
}
然后将其实现为
impl<'a> Exec<'a> for Holder<'a> {
fn exec(&'a self, v: &'a usize) -> usize {
self.exec_aux(v)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.