我有这种类型:
struct Wrap<T>(Vec<T>);
Run Code Online (Sandbox Code Playgroud)
我想实现std::ops::Index并返回对特征对象的引用.这是我的第一次尝试(游乐场):
use std::ops::Index;
use std::fmt::Display;
impl<T> Index<usize> for Wrap<T>
where
T: Display
{
type Output = Display;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用并导致此错误:
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:13:9
|
7 | impl<T> Index<usize> for Wrap<T>
| - help: consider adding an explicit lifetime bound `T: 'static`...
...
13 | &self.0[index]
| ^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet …Run Code Online (Sandbox Code Playgroud) 我正在阅读Trait Objects 需要对象安全,但我不明白泛型类型参数的问题。
使用 trait 时用具体类型参数填充的泛型类型参数也是如此:具体类型成为实现 trait 的类型的一部分。当通过使用 trait 对象忘记类型时,无法知道用什么类型填充泛型类型参数。
我正在尝试编写一个示例,但我无法理解。什么是泛型类型参数?
我试图从一个参数化的 trait 中创建一个 trait 对象,但是一旦参数被赋予了一个具体的值,它就可以正常工作:
trait Creator<T> {
fn create(&self) -> T;
}
struct CreationHouse {
creators: Vec<Box<dyn Creator<u32>>>
}
struct NumCreator { seed: u32 }
impl Creator<u32> for NumCreator {
fn create(&self) -> u32 {
return self.seed;
}
}
fn main() {
let ch = CreationHouse{
creators: vec![Box::new(NumCreator{seed: 3})]
};
}
Run Code Online (Sandbox Code Playgroud)
(编译良好,除了“未使用”警告)
我不明白的是“使用特征时用具体类型参数填充的泛型类型参数”是什么意思,以及泛型类型怎么会丢失(因为特征“携带”它们自己)。如果你能写一个段落中描述的案例的例子,我将不胜感激。
这是我的代码:
use std::rc::{Rc, Weak};
use std::cell::RefCell;
trait Trait {}
fn push<E: Trait>(e: E) {
let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();
// let x = Rc::new(RefCell::new(Box::new(e)));
// v.push(x); // error
v.push(Rc::new(RefCell::new(Box::new(e)))); // works fine
}
Run Code Online (Sandbox Code Playgroud)
将v.push(x)引发此错误:
error[E0308]: mismatched types
--> src/main.rs:12:12
|
7 | fn push<E: Trait>(e: E) {
| - this type parameter
...
12 | v.push(x);
| ^ expected trait object `dyn Trait`, found type parameter `E`
|
= note: expected struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn Trait>>>`
found struct …Run Code Online (Sandbox Code Playgroud) polymorphism traits rust parametric-polymorphism trait-objects
锈病书上说,它是地道的使用Rc::clone(&x),而不是x.clone()用Rc值,这样很明显,这不是典型的clone。我完全赞成这一点,但我在实践中无法应用该理论。
我想克隆一个引用计数的结构,但将克隆转换为特征对象。我可以使用rc.clone(),但不能使用Rc::clone(&rc). 这对我来说……很奇怪。
struct ListView {}
trait View {}
impl View for ListView {}
fn very_contrived_example() {
let list_view: Rc<ListView> = Rc::new(ListView {});
let mut views: Vec<Rc<dyn View>> = Vec::new();
// Using Rc::clone does not work:
// error[E0308]: mismatched types
//
// views.push(Rc::clone(&list_view));
// ^^^^^^^^^^ expected trait object `dyn View`, found struct `ListView`
//
// note: expected reference `&Rc<dyn View>`
// found reference `&Rc<ListView>`
// Using …Run Code Online (Sandbox Code Playgroud) 有没有办法在堆栈内存中完全实现 trait 对象?
这是我使用的代码,Box因此是堆内存:
extern crate alloc;
use alloc::vec::Vec;
use alloc::boxed::Box;
pub trait ConnectionImp {
fn send_data(&self);
}
pub struct Collector {
pub connections: Vec<Box<dyn ConnectionImp>>
}
impl Collector {
pub fn new() -> Collector {
Collector {
connections: Vec::with_capacity(5),
}
}
pub fn add_connection(&mut self,conn: Box<dyn ConnectionImp> ){
self.connections.push(conn);
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用无堆板条箱,但找不到Box. 以下代码显示了我的努力结果:
use heapless::{Vec,/*pool::Box*/};
extern crate alloc;
use alloc::boxed::Box;
pub trait ConnectionImp {
fn send_data(&self);
}
pub struct Collector {
pub connections: …Run Code Online (Sandbox Code Playgroud) 我正在努力解决对象安全的基础问题.如果我有这个代码
struct S {
x: i32
}
trait Trait: Sized {
fn f(&self) -> i32 where Self: Sized;
}
fn object_safety_dynamic(x: Trait) {}
Run Code Online (Sandbox Code Playgroud)
我收到
fn object_safety_dynamic(x: Trait) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `traits::Trait` cannot be made into an object
= note: the trait cannot require that `Self : Sized`
Run Code Online (Sandbox Code Playgroud)
当添加/更改:Sized为特征的继承或f绑定时,我收到稍微不同的错误消息.
有人能解释一下:
为什么这个特定的例子不起作用?Trait Objects一章说明"那么什么使方法对象安全?每种方法都必须要求Self: Sized".那不是满满的吗?
Trait: Sized和之间有什么区别where Self: Sized?(嗯,是的,一个继承了特性,另一个是参数绑定,但是从Rust的特质对象的角度来看?
我必须做的首选改变是什么object_safety_dynamic?
rustc 1.19.0-nightly (01951a61a 2017-05-20) …
A Mech带有一个驱动程序,它是一个Named实体.在运行时,省略的Mech构造函数会查询要使用的特定类型驱动程序的外部源.
trait Named {
fn name(self) -> String;
}
struct Person {
first_name: String,
last_name: String
}
impl Named for Person {
fn name(self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
pub struct Mech<'a> {
driver: Box<Named + 'a>,
}
impl<'a> Mech<'a> {
pub fn driver_name(self) -> String {
self.driver.name()
}
}
Run Code Online (Sandbox Code Playgroud)
方法driver_name将所有权返回给a String,以便在链式调用中进一步使用(在实际代码中它是a Command).它编译失败:
error[E0161]: cannot move a value of type Named + 'a: the size of …Run Code Online (Sandbox Code Playgroud) 考虑我有一个函数make_numbers应该创建一串随机数的情况,但我想在运行时(用户输入)决定应该使用哪种随机数生成器.为了使它更加困难,让我们假设make_numbers函数对于要生成的数字类型是通用的.
我用伪代码编写了我想要实现的内容,并且我理解为什么这不起作用.但是,我不知道Rust的惯用方式是什么样的呢?
我天真的想法是:
Box<Rng>,但由于Rng具有通用功能,因此不起作用.StdRng和XorShiftRng,但我真的不能想到一个很好的方式来写这个.你能给我一些提示,看看这个特殊问题的解决方案是什么样的吗?
注意:这个问题不是关于具有不同类型的不同匹配臂(解决方案可能是Box枚举,如上所述) - 而是如何在这种情况下应用这些解决方案.
extern crate rand;
use rand::{Rng, SeedableRng, StdRng};
use rand::prng::XorShiftRng;
use std::string::String;
use rand::distributions::{Distribution, Standard};
use std::fmt::Display;
// Generic function that should work with any type of random number generator
fn make_numbers<T, R: Rng>(rng: &mut R) -> String
where T: Display, Standard: Distribution<T>
{
let mut s = String::new();
for _i in 0..10 {
s.push_str(format!("_{}", rng.gen::<T>()).as_str());
}
s …Run Code Online (Sandbox Code Playgroud) fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
do_twice(|x| x + 1, 5) // call
Run Code Online (Sandbox Code Playgroud)
该函数接受闭包和函数指针.它将函数指针作为参数类型.
什么时候我应该更喜欢使用特征对象,比如&dyn Fn(i32) -> i32或Box<dyn Fn(i32)-> i32>代替fn
fn do_twice(f: &dyn Fn(i32) -> i32, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
do_twice(&|x| x + 1, 5) // call
Run Code Online (Sandbox Code Playgroud)
要么
fn do_twice(f: Box<dyn Fn(i32) -> i32>, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
Run Code Online (Sandbox Code Playgroud) 我对 Rust 还很陌生,所以这可能是一个简单的问题。
我正在尝试为处理程序创建一个小型注册表,该注册表应返回实现该TransferObject特征的任何结构:
pub trait TransferObject: Hash + PartialEq {}
Run Code Online (Sandbox Code Playgroud)
HashMap由于我存储在Trait中注册的处理程序,因此需要Hash和PartialEq作为 Supertraits:
pub struct RequestHandlerRegistry {
handlers: HashMap<RequestMethod, HashMap<String, RequestHandler<dyn TransferObject>>>,
}
Run Code Online (Sandbox Code Playgroud)
但在结构中,我收到错误,因为使用了参数,TransferObject所以无法将其制成对象。我已经尝试过做这样的事情:PartialEqSelf
pub struct RequestHandlerRegistry {
handlers: HashMap<RequestMethod, HashMap<String, RequestHandler<Box<dyn TransferObject>>>>,
}
Run Code Online (Sandbox Code Playgroud)
但我仍然遇到同样的错误。
有什么办法可以解决这个问题吗?
我还创建了一个Playground来轻松重现错误。
rust ×10
trait-objects ×10
traits ×7
closures ×1
function ×1
generics ×1
ownership ×1
polymorphism ×1