我有一个由某些结构实现的特征.我想写一个模式匹配,我可以处理每个可能的情况:
trait Base {}
struct Foo {
x: u32,
}
struct Bar {
y: u32,
}
impl Base for Foo {}
impl Base for Bar {}
fn test(v: bool) -> Box<Base + 'static> {
if v {
Box::new(Foo { x: 5 })
} else {
Box::new(Bar { y: 10 })
}
}
fn main() {
let f: Box<Base> = test(true);
match *f {
Foo { x } => println!("it was Foo: {}!", x),
Bar { y } => println!("it was …Run Code Online (Sandbox Code Playgroud) 这个函数的实现是什么:
fn unbox<T>(value: Box<T>) -> T {
// ???
}
Run Code Online (Sandbox Code Playgroud)
文档中唯一看起来像我想要的功能Box::into_raw.以下将进行类型检查:
fn unbox<T>(value: Box<T>) -> T {
*value.into_raw()
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误error[E0133]: dereference of raw pointer requires unsafe function or block.将其包装在一个unsafe { ... }块中可以修复它.
fn unbox<T>(value: Box<T>) -> T {
unsafe { *value.into_raw() }
}
Run Code Online (Sandbox Code Playgroud)
这是正确的实施吗?如果是这样,为什么它不安全?这是什么意思?
也许这个问题显示了我对如何Box实际工作的一般不确定性.
我正试图在Rust中操纵AST.会有很多操作,我希望我的树是不可变的,所以为了节省时间,所有引用都将是Rcs.
我的树节点将如下所示:
enum Condition {
Equals(Rc<Expression>, Rc<Expression>),
LessThan(Rc<Expression>, Rc<Expression>),
...
}
enum Expression {
Plus(Rc<Expression>, Rc<Expression>),
...
}
Run Code Online (Sandbox Code Playgroud)
我想用另一个相同类型的节点替换给定类型的随机节点.要在树上进行通用操作,我已经做了一个特性:
trait AstNode {
fn children(&self) -> Vec<Rc<AstNode>>;
}
Run Code Online (Sandbox Code Playgroud)
所有节点都实现了这一点.这允许我通过简单地调用来遍历树而不必为每个操作解构每个节点类型children().
我还希望克隆一个节点,同时只更新其中一个子节点,并保留其他子节点.假设我已经能够生成正确的具体类型的节点(如果我错了,我很高兴程序会出现恐慌).我将在特征中添加以下方法:
trait AstNode {
fn clone_with_children(&self, new_children: Vec<Rc<AstNode>>) -> Self
where Self: Sized;
}
Run Code Online (Sandbox Code Playgroud)
我的计划是把孩子们带回来childen(),替换他们中的一个,然后调用clone_with_children()构建一个相同枚举变量的节点,但是替换了一个节点.
我的问题是如何写clone_with_children().
我需要向下转换Rc<AstNode>到Rc<Expression>(或你有什么),同时保持内部的引用计数Rc相同,但没有我已经找到了向下转换库似乎是能够做到这一点.
我想要的是什么,或者我应该完全不同地做到这一点?
我试图为结构创建一个通用向量时遇到了问题.这是我的第一次尝试:
#[derive(Serialize)]
struct Card {
sections: Vec<Section<WidgetTrait>>
}
#[derive(Serialize)]
struct Section<T: WidgetTrait> {
header: String,
widgets: Vec<T>
}
Run Code Online (Sandbox Code Playgroud)
这使我遇到了一个Sized未实现的错误,并且WidgetTrait在编译时未知大小.
我的下一次尝试是这样使用Box<WidgetTrait>:
#[derive(Serialize)]
struct Section {
header: String,
widgets: Vec<Box<WidgetTrait>>
}
Run Code Online (Sandbox Code Playgroud)
这导致了一个错误:
error[E0277]: the trait bound `WidgetTrait: serde::Serialize` is not satisfied
--> src/main.rs:11:10
|
11 | #[derive(Serialize)]
| ^^^^^^^^^ the trait `serde::Serialize` is not implemented for `WidgetTrait`
|
= note: required because of the requirements on the impl of `serde::Serialize` for `std::boxed::Box<WidgetTrait>`
= note: required …Run Code Online (Sandbox Code Playgroud) pub struct WidgetWrap {
// ...
widget: RefCell<Box<Any>>,
}
Run Code Online (Sandbox Code Playgroud)
在某些时候,我想投Box<Any>给Box<WidgetTrait>
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait>>();
Run Code Online (Sandbox Code Playgroud)
这给了我这样的错误:
error: instantiating a type parameter with an incompatible type
`Box<WidgetTrait>`, which does not fulfill `'static` [E0144]
Run Code Online (Sandbox Code Playgroud)
这究竟意味着什么?
我看过如何解决:值可能包含引用; 添加`'static`绑定到`T`并尝试添加+ 'static到处.
pub struct WidgetWrap {
// ...
widget: RefCell<Box<Any + 'static>>,
}
let mut cell = widget.borrow_mut();
let w = cell.downcast_mut::<Box<WidgetTrait + 'static>>();
Run Code Online (Sandbox Code Playgroud)
它修复了编译错误,但是当我尝试打开如下所示的downcasrap框时失败.是的,盒子的内容是一个实现的对象WidgetTrait.
显然,我在Rust中的编码水平我不太了解,但也许有人可以帮助我更好地掌握上述任务中涉及的概念.
我有一个带有类型参数的函数,U它返回一个Option<U>. U受 trait 的约束num::Num。这样,U可以是usize,u8,u16,u32,u64,u128,isize,等。
我如何匹配U?例如,
match U {
u8 => {},
u16 => {}
_ => {}
}
Run Code Online (Sandbox Code Playgroud) 我希望能够使用各种不同类型作为 a 中的键HashMap,所有这些都可以实现Hash。这似乎应该是可能的:从阅读文档来看,似乎每个Hasher都会产生一个u64结果,因此它们最终会简化为通用类型。实际上我想做的是:
use std::{collections::HashMap, hash::Hash};
fn x(_: HashMap<Box<dyn Hash>, ()>) {}
Run Code Online (Sandbox Code Playgroud)
我不被允许这样做:
error[E0038]: the trait `std::hash::Hash` cannot be made into an object
--> src/lib.rs:3:9
|
3 | fn x(_: HashMap<Box<dyn Hash>, ()>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::hash::Hash` cannot be made into an object
Run Code Online (Sandbox Code Playgroud)
似乎我可以创建一个Hasher(例如RandomState),用它来手动计算哈希值,然后将u64结果存储在 a 中HashMap<u64, _>,但这似乎过于复杂。我不想再次获取键值,我只需要能够比较哈希值。有HashMap我不知道的替代方案吗?或者我以完全错误的方式看待这个问题?
如何将特征向下转换为结构,就像这个 C# 示例中那样?
我有一个基本特征和几个派生结构,必须将它们推入单个基本特征向量中。
我必须检查向量的每个项目是否可转换为特定的派生结构,如果是,则将其用作该类型的结构。
这是我的 Rust 代码,我不知道如何实现注释部分。
trait Base {
fn base_method(&self);
}
struct Derived1;
impl Derived1 {
pub fn derived1_method(&self) {
println!("Derived1");
}
}
impl Base for Derived1 {
fn base_method(&self) {
println!("Base Derived1");
}
}
struct Derived2;
impl Derived2 {
pub fn derived2_method(&self) {
println!("Derived2");
}
}
impl Base for Derived2 {
fn base_method(&self) {
println!("Base Derived2");
}
}
fn main() {
let mut bases = Vec::<Box<dyn Base>>::new();
let der1 = Derived1{};
let der2 …Run Code Online (Sandbox Code Playgroud) rust ×8
downcast ×3
hashmap ×1
match ×1
polymorphism ×1
serde ×1
traits ×1
type-systems ×1
types ×1
unsafe ×1