gpt4 book ai didi

rust - 如何使用 remove 方法扩展基于枚举的多类型容器?

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

此问题基于 another recent question of mine 中给出的信息.我想扩展以下 Containerremove将存储数据的所有权返回给调用者的方法。随附的单元测试应解释其所需的行为。

在之前的案例中(参见引用问题),我会使用 downcast Box<Any> 上的方法对象,但我不知道在使用枚举的情况下如何解决这个问题。感谢指点。

use std::any::{Any, TypeId};
use std::collections::HashMap;

trait GroupTrait {
fn borrow<T: Any>(&self) -> Option<&T>;
}

struct Container<G> {
inner: HashMap<TypeId, G>,
}

impl<G> Default for Container<G>
where
G: GroupTrait,
{
fn default() -> Self {
Container {
inner: Default::default(),
}
}
}

impl<G> Container<G>
where
G: GroupTrait,
{
pub fn insert<T: Any + Into<G>>(&mut self, data: T) {
self.inner.insert(TypeId::of::<T>(), data.into());
}
pub fn borrow<T: Any>(&self) -> Option<&T> {
self.inner.get(&TypeId::of::<T>()).and_then(|g| g.borrow())
}
pub fn remove<T: Any>(&mut self) -> Option<T> {
unimplemented!()
}
}

#[cfg(test)]
mod tests {
use super::*;

/// This should be an user-defined type that implements the Any trait.
#[derive(Debug, Clone, PartialEq)]
struct TypeA(u32);

/// This should be an user-defined type that implements the Any trait.
#[derive(Debug, Clone, PartialEq)]
struct TypeB(String);

/// This is the enum that should replace boxed `Any` trait objects. Users also need to supply
/// this enum. Maybe they'll need to implement additional traits to get `borrow` to work.
#[derive(Debug, PartialEq)]
enum Group {
A(TypeA),
B(TypeB),
}

impl From<TypeA> for Group {
fn from(value: TypeA) -> Self {
Group::A(value)
}
}

impl From<TypeB> for Group {
fn from(value: TypeB) -> Self {
Group::B(value)
}
}

impl GroupTrait for Group {
fn borrow<T: Any>(&self) -> Option<&T> {
use self::Group::*;
match *self {
A(ref i) => Any::downcast_ref(i),
B(ref i) => Any::downcast_ref(i),
}
}
}

#[test]
fn insert() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
assert_eq!(
c.inner.get(&TypeId::of::<TypeA>()),
Some(&Group::A(data.clone()))
);
}

#[test]
fn borrow() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
let borrowed = c.borrow::<TypeA>();
assert_eq!(borrowed, Some(&data));
}

#[test]
fn remove() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
assert_eq!(c.remove::<TypeA>(), Some(data));
}
}

最佳答案

正如您在评论中提到的,TryFrom是可能的。但是,我会选择 Into<Option<T>> :

pub fn remove<T: Any>(&mut self) -> Option<T>
where
G: Into<Option<T>>,
{
self.inner.remove(&TypeId::of::<T>()).and_then(|g| g.into())
}

Playground

我会选择 Into<Option<T>>TryInto<T>因为Into<Option<T>>结果 Option同时 TryInto<T>结果 Result<T, Self::Error>

关于rust - 如何使用 remove 方法扩展基于枚举的多类型容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49491819/

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