标签: trait-objects

如何使用非关联类型的非静态特征对象?

我有这种类型:

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)

traits rust associated-types trait-objects

4
推荐指数
1
解决办法
288
查看次数

在 trait 对象中使用泛型类型参数的引用问题是什么?

我正在阅读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)

(编译良好,除了“未使用”警告)

我不明白的是“使用特征时用具体类型参数填充的泛型类型参数”是什么意思,以及泛型类型怎么会丢失(因为特征“携带”它们自己)。如果你能写一个段落中描述的案例的例子,我将不胜感激。

generics traits rust trait-objects

4
推荐指数
2
解决办法
990
查看次数

为什么除非我使用临时变量,否则我不能推入 dyn Trait 的 Vec?

这是我的代码:

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

4
推荐指数
1
解决办法
656
查看次数

如何在转换为 trait 对象时使用 Rc::clone?

锈病书上说,它是地道的使用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)

rust trait-objects

4
推荐指数
1
解决办法
54
查看次数

是否有无堆的 trait 对象?

有没有办法在堆栈内存中完全实现 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)

rust trait-objects

4
推荐指数
1
解决办法
88
查看次数

了解特征和对象安全

我正在努力解决对象安全的基础问题.如果我有这个代码

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) …

traits rust trait-objects

3
推荐指数
2
解决办法
1279
查看次数

如何从对象安全的特征对象中移出一个值?

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)

traits ownership rust trait-objects

3
推荐指数
1
解决办法
206
查看次数

泛型加动态调度

考虑我有一个函数make_numbers应该创建一串随机数的情况,但我想在运行时(用户输入)决定应该使用哪种随机数生成器.为了使它更加困难,让我们假设make_numbers函数对于要生成的数字类型是通用的.

我用伪代码编写了我想要实现的内容,并且我理解为什么这不起作用.但是,我不知道Rust的惯用方式是什么样的呢?

我天真的想法是:

  1. 使用Box<Rng>,但由于Rng具有通用功能,因此不起作用.
  2. 使用枚举了StdRngXorShiftRng,但我真的不能想到一个很好的方式来写这个.

你能给我一些提示,看看这个特殊问题的解决方案是什么样的吗?

注意:这个问题不是关于具有不同类型的不同匹配臂(解决方案可能是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)

traits rust trait-objects

3
推荐指数
1
解决办法
107
查看次数

函数指针vs Fn trait对象

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) -> i32Box<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)

closures function traits rust trait-objects

3
推荐指数
2
解决办法
495
查看次数

当 Hash + PartialEq 为 Supertraits 时,Trait 无法成为对象安全

我对 Rust 还很陌生,所以这可能是一个简单的问题。

我正在尝试为处理程序创建一个小型注册表,该注册表应返回实现该TransferObject特征的任何结构:

pub trait TransferObject: Hash + PartialEq {}
Run Code Online (Sandbox Code Playgroud)

HashMap由于我存储在Trait中注册的处理程序,因此需要HashPartialEq作为 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 trait-objects

3
推荐指数
1
解决办法
692
查看次数