是否可以为具有有限生命周期的特征对象实现克隆(不使用不安全代码)?
Can Clone be implemented for a trait object with finite lifetime (without using unsafe code)?
要事第一:我要实现什么目标?
我正在尝试将 Iterator::fold()
与本身是 Iterator
的累加器一起使用,但此外我还需要内部迭代器的克隆。
fn whatever<T,U,V,W>(some_iterator : T, other_cloneable_iterator_init : U) -> impl Iterator<Item=W>
where T: Iterator<Item=V>,
U: Iterator<Item=W>+Clone
{
some_iterator.fold(other_cloneable_iterator_init,|other_cloneable_iterator, value| {
let computed_value =
some_function_that_consumes_an_iterator(other_cloneable_iterator.clone(), value);
other_iterator.filter(|other_value| some_function(computed_value, other_value))
}
}
这当然不能像上面写的那样工作,因为给fold
的闭包的return类型与初始化器的类型不同。
为什么这个问题会导致这个问题?
然而,它们的共同点是都实现了 Iterator<Item=W>+Clone
特性。这几乎是在尖叫“通过使类型成为特征对象来擦除类型”。
如果它只是 Iterator<Item=W>
特质,我就会那样做。但是,Clone
特性不是对象安全的。在线搜索“clone boxed trait object”会产生各种讨论,所有讨论都 on the trait object (what Iterators
usually do not have), or using unsafe code (which I would like to avoid) like the dyn-clone crate。
实际问题:
因此,如果想避免使用不安全代码,并且没有获得 'static
生命周期的奢侈,那么如何为装箱特征对象实现 Clone
呢?
我说的是像下面这样的代码,它存在生命周期问题并且无法编译:
trait Cu32Tst<'a> : Iterator<Item=u32>+'a {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a>;
}
impl<'a, T : Iterator<Item=u32>+Clone+'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>>{
fn clone(&self) -> Self {
self.box_clone()
}
}
我想在 Box
上使用 Clone
的原因是,为了将其用作累加器类型,我必须能够从输出中创建一个新的 Box<dyn IteratorTraitObject>
Iterator::filter()
方法的方法,如果调用它的迭代器是 Clone
,则它只是 Clone
(然后我必须为 Box
实现 Iterator
作为好吧,但这可以转发到包含的值)。
长话短说:可以 Clone
为具有有限生命周期的特征对象实现吗?如果可以,如何实现?
您需要修改代码以实现 Box<dyn Cu32Tst<'a>>
而不是 Box<dyn Cu32Tst + 'a>
。后者大概实现了 Cu32Tst<'static>
,这不是你想要的 Clone
对 Cu32Tst<'a>
的全面实现。这编译:
trait Cu32Tst<'a>: Iterator<Item = u32> + 'a {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>>;
}
impl<'a, T: Iterator<Item = u32> + Clone + 'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>> {
fn clone(&self) -> Self {
self.as_ref().box_clone()
}
}
请注意,Clone
实现使用 self.as_ref().box_clone()
调用 box_clone()
。这是因为 Cu32Tst
的整体实现与 Box<dyn Cu32Tst>
相匹配,因为它既是 Clone
又是 Iterator
,所以盒子本身有一个 box_clone()
方法。结果,self.box_clone()
可以编译,但会导致无限递归。
要事第一:我要实现什么目标?
我正在尝试将 Iterator::fold()
与本身是 Iterator
的累加器一起使用,但此外我还需要内部迭代器的克隆。
fn whatever<T,U,V,W>(some_iterator : T, other_cloneable_iterator_init : U) -> impl Iterator<Item=W>
where T: Iterator<Item=V>,
U: Iterator<Item=W>+Clone
{
some_iterator.fold(other_cloneable_iterator_init,|other_cloneable_iterator, value| {
let computed_value =
some_function_that_consumes_an_iterator(other_cloneable_iterator.clone(), value);
other_iterator.filter(|other_value| some_function(computed_value, other_value))
}
}
这当然不能像上面写的那样工作,因为给fold
的闭包的return类型与初始化器的类型不同。
为什么这个问题会导致这个问题?
然而,它们的共同点是都实现了 Iterator<Item=W>+Clone
特性。这几乎是在尖叫“通过使类型成为特征对象来擦除类型”。
如果它只是 Iterator<Item=W>
特质,我就会那样做。但是,Clone
特性不是对象安全的。在线搜索“clone boxed trait object”会产生各种讨论,所有讨论都 Iterators
usually do not have), or using unsafe code (which I would like to avoid) like the dyn-clone crate。
实际问题:
因此,如果想避免使用不安全代码,并且没有获得 'static
生命周期的奢侈,那么如何为装箱特征对象实现 Clone
呢?
我说的是像下面这样的代码,它存在生命周期问题并且无法编译:
trait Cu32Tst<'a> : Iterator<Item=u32>+'a {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a>;
}
impl<'a, T : Iterator<Item=u32>+Clone+'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst+'a> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>>{
fn clone(&self) -> Self {
self.box_clone()
}
}
我想在 Box
上使用 Clone
的原因是,为了将其用作累加器类型,我必须能够从输出中创建一个新的 Box<dyn IteratorTraitObject>
Iterator::filter()
方法的方法,如果调用它的迭代器是 Clone
,则它只是 Clone
(然后我必须为 Box
实现 Iterator
作为好吧,但这可以转发到包含的值)。
长话短说:可以 Clone
为具有有限生命周期的特征对象实现吗?如果可以,如何实现?
您需要修改代码以实现 Box<dyn Cu32Tst<'a>>
而不是 Box<dyn Cu32Tst + 'a>
。后者大概实现了 Cu32Tst<'static>
,这不是你想要的 Clone
对 Cu32Tst<'a>
的全面实现。这编译:
trait Cu32Tst<'a>: Iterator<Item = u32> + 'a {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>>;
}
impl<'a, T: Iterator<Item = u32> + Clone + 'a> Cu32Tst<'a> for T {
fn box_clone(&self) -> Box<dyn Cu32Tst<'a>> {
Box::new(self.clone())
}
}
impl<'a> Clone for Box<dyn Cu32Tst<'a>> {
fn clone(&self) -> Self {
self.as_ref().box_clone()
}
}
请注意,Clone
实现使用 self.as_ref().box_clone()
调用 box_clone()
。这是因为 Cu32Tst
的整体实现与 Box<dyn Cu32Tst>
相匹配,因为它既是 Clone
又是 Iterator
,所以盒子本身有一个 box_clone()
方法。结果,self.box_clone()
可以编译,但会导致无限递归。