gpt4 book ai didi

rust - 将泛型类型绑定(bind)到需要生命周期的特征时未使用的类型参数

转载 作者:行者123 更新时间:2023-11-29 08:27:20 24 4
gpt4 key购买 nike

use std::collections::HashMap;
use std::hash::Hash;

struct Watchable<'a, K, V, W: Watcher<'a, K, V>> {
data: HashMap<K, V>,
watchers: Vec<W>,
}

trait Watcher<'a, K, V> {
fn before_new(&mut self, key: &'a K, value: &'a V);
}

struct IndexWatcher<'a, I: 'a, V: 'a> {
data: HashMap<&'a I, &'a V>,
indexer: fn(&V) -> &I,
}

impl<'a, K, V, I> Watcher<'a, K, V> for IndexWatcher<'a, I, V>
where I: Eq + Hash
{
fn before_new(&mut self, key: &'a K, value: &'a V) {
let index = (self.indexer)(value);
self.data.insert(index, value);
}
}
error[E0392]: parameter `'a` is never used
--> src/main.rs:4:18
|
4 | struct Watchable<'a, K, V, W: Watcher<'a, K, V>> {
| ^^ unused type parameter
|
= help: consider removing `'a` or using a marker such as `std::marker::PhantomData`

有什么方法可以删除一些生命周期注释吗?似乎所有东西都有相同的生命周期a

起初,我没有输入任何具体的生命周期:

struct IndexWatcher<I, V> {
data: HashMap<&I, &V>,
indexer: fn(&V) -> &I,
}

编译器提示生命周期,所以我添加了它:

struct IndexWatcher<'a, I: 'a, V: 'a> {
data: HashMap<&'a I, &'a V>,
indexer: fn(&V) -> &I,
}

当我尝试实现没有生命周期的特征时:

trait Watcher<K, V> {
fn before_new(&mut self, key: &K, value: &V);
}

impl<'a, K, V, I> Watcher<K, V> for IndexWatcher<'a, I, V>
where I: Eq + Hash
{
fn before_new(&mut self, key: &K, value: &V) {
let index = (self.indexer)(value);
self.data.insert(index, value);
}
}

我得到了错误:

error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> <anon>:18:33
|
18 | self.data.insert(index, value);
| ^^^^^
|

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> <anon>:17:21
|
17 | let index = (self.indexer)(value);
| ^^^^^^^^^^^^^^^^^^^^^
|

因此我的最终版本到处都是生命周期。

理想情况下,我想像下面这样在 Watchable 中使用 trait:

impl<K, V, W: Watcher<K, V>> Watchable<K, V, W>
where K: Eq + Hash {

fn insert(&mut self, k: K, v: V) -> Option<V> {
match self.data.entry(k) {
Occupied(mut occupied) => {
{
let k = occupied.key();
let old = occupied.get();
for watcher in &mut self.watchers {
watcher.before_change(k, &v, old);
}
}
let old = occupied.insert(v);
Some(old)
},
Vacant(vacant) => {
{
let k = vacant.key();
for watcher in &mut self.watchers {
watcher.before_new(k, &v);
}
}
vacant.insert(v);
None
}
}
}
}

trait Watcher<K, V> {
fn before_new(&mut self, key: &K, value: &V);
fn before_change(&mut self, key: &K, value: &V, old: &V);
}

最佳答案

您可以使用 higher-rank trait bound 来消除错误而不是生命周期参数:

struct Watchable<K, V, W: for<'a> Watcher<'a, K, V>> {
data: HashMap<K, V>,
watchers: Vec<W>,
}

但这并不能解决您的问题。 IndexWatcher不会满足边界 for<'a> Watcher<'a, K, V>因为 IndexWatcher<'a, I, V>只实现 Watcher<'a, K, V>对于一个特定的生命周期,而不是所有可能的生命周期。

从根本上说,问题在于 you're trying to put a value and a reference to that value in the same struct (间接地)。也就是说,您的想法是希望观察者从 Watchable 中借用数据。 ,但是 Watchable还拥有观察者。请抓紧时间read this question以及 Shepmaster 的回答,以了解为什么这个想法行不通。

特别注意,在 Watchable 中插入条目或从中删除条目的 HashMap由于 HashMap,可能会使任何观察者中的引用无效需要重新分配存储,这可能会导致键和值的地址发生变化。

我会做的是将键和值包装在 Rc 中(或者 Arc 如果你想跨线程共享 Watchable)。从 Rc<V> 中获取共享索引值虽然可能有问题。考虑将索引函数更改为 fn(&V) -> I ,并让索引函数返回克隆(如果克隆索引值太昂贵,它们可以是 Rc 的克隆)或句柄。

关于rust - 将泛型类型绑定(bind)到需要生命周期的特征时未使用的类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43684768/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com