Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何将动态分派与以迭代器为参数的方法结合使用?_Rust_Iterator_Traits_Dynamic Dispatch - Fatal编程技术网

Rust 如何将动态分派与以迭代器为参数的方法结合使用?

Rust 如何将动态分派与以迭代器为参数的方法结合使用?,rust,iterator,traits,dynamic-dispatch,Rust,Iterator,Traits,Dynamic Dispatch,我正在用rust编写一个命令行应用程序,用于处理来自传感器的音频。我希望用户能够从几个选项中选择要应用的算法或过滤器。我希望使用动态分派来切换出一个在运行时实现我的过滤器特性的结构。但是,编译器不允许这样做,因为其中一个trait方法使用泛型参数 如何实现相同的功能,而不引起任何编译器问题?我知道一个简单的解决方案是将process方法的参数更改为数组或向量,但这是我最后的选择,因为我更喜欢使用迭代器或IntoIterator,因为它更通用,并且适合我的特定需要 下面是一些演示问题的代码 tra

我正在用rust编写一个命令行应用程序,用于处理来自传感器的音频。我希望用户能够从几个选项中选择要应用的算法或过滤器。我希望使用动态分派来切换出一个在运行时实现我的过滤器特性的结构。但是,编译器不允许这样做,因为其中一个trait方法使用泛型参数

如何实现相同的功能,而不引起任何编译器问题?我知道一个简单的解决方案是将process方法的参数更改为数组或向量,但这是我最后的选择,因为我更喜欢使用迭代器或IntoIterator,因为它更通用,并且适合我的特定需要

下面是一些演示问题的代码

trait SensorFilter {
    fn process(&self, sig: &mut impl Iterator<Item = f32>) -> Vec<f32>;
}

struct Alg1 {
    mul: f32,
}

struct Alg2 {
    add: f32,
}

impl SensorFilter for Alg1 {
    fn process(&self, sig: &mut impl Iterator<Item = f32>) -> Vec<f32> {
        sig.map(|x| x * self.mul).collect()
    }
}

impl SensorFilter for Alg2 {
    fn process(&self, sig: &mut impl Iterator<Item = f32>) -> Vec<f32> {
        sig.map(|x| x * self.add).collect()
    }
}

enum AlgChoice {
    Alg1,
    Alg2
}

fn main() {
    let choice = AlgChoice::Alg1; // user chooses via command-line.
    let mut sig = vec![0.,1.,2.,3.,4.,5.,6.].into_iter(); // iterator gets data from sensor.

    // This doesn't work, because my trait cannot be made into an object.
    let alg: &dyn SensorFilter = match choice {
        AlgChoice::Alg1 => Alg1{mul:0.3},
        _ => Alg2{add:1.2},
    };

    let result = alg.process(&mut sig);
    println!("{:?}",result);
}

trait传感器过滤器{
fn进程(&self,sig:&mut impl迭代器)->Vec;
}
结构Alg1{
mul:f32,
}
结构Alg2{
地址:f32,
}
用于Alg1的impl传感器滤波器{
fn进程(&self,sig:&mut impl迭代器)->Vec{
sig.map(| x | x*self.mul.collect())
}
}
用于Alg2的impl传感器滤波器{
fn进程(&self,sig:&mut impl迭代器)->Vec{
sig.map(| x | x*self.add).collect()
}
}
枚举选择{
Alg1,
Alg2
}
fn main(){
let choice=AlgChoice::Alg1;//用户通过命令行进行选择。
让mut sig=vec![0,1,2,3,4,5,6.].进入_iter();//迭代器从传感器获取数据。
//这不起作用,因为我的特征不能被制成一个物体。
让alg:&dyn SensorFilter=匹配选项{
AlgChoice::Alg1=>Alg1{mul:0.3},
_=>Alg2{add:1.2},
};
让结果=分析过程(&mut sig);
println!(“{:?}”,结果);
}

谢谢:)

这里的技巧是将通用函数参数更改为通用特性参数:

// Make the generic param into a type argument w/ constraints
trait SensorFilter<I> where I: Iterator<Item = f32> {
    fn process(&self, sig: &mut I) -> Vec<f32>;
}

struct Alg1 {
    mul: f32,
}

struct Alg2 {
    add: f32,
}

// Implement trait for all I that match the iterator constraint
impl<I: Iterator<Item = f32>> SensorFilter<I> for Alg1 {
    fn process(&self, sig: &mut I) -> Vec<f32> {
        sig.map(|x| x * self.mul).collect()
    }
}

impl<I: Iterator<Item = f32>> SensorFilter<I> for Alg2 {
    fn process(&self, sig: &mut I) -> Vec<f32> {
        sig.map(|x| x * self.add).collect()
    }
}

enum AlgChoice {
    Alg1,
    Alg2
}

fn main() {
    let choice = AlgChoice::Alg1; // user chooses via command-line.
    let mut sig = vec![0.,1.,2.,3.,4.,5.,6.].into_iter(); // iterator gets data from sensor.

    // Specify the type argument of your trait.
    let alg: &dyn SensorFilter<std::vec::IntoIter<f32>> = match choice {
        AlgChoice::Alg1 => &Alg1{mul:0.3},
        _ => &Alg2{add:1.2}, 
    };

    let result = alg.process(&mut sig);
    println!("{:?}",result);
}
//将泛型参数设置为带约束的类型参数
特征传感器过滤器,其中I:迭代器{
fn流程(&self,sig:&mut I)->Vec;
}
结构Alg1{
mul:f32,
}
结构Alg2{
地址:f32,
}
//为所有匹配迭代器约束的I实现trait
用于Alg1的impl传感器滤波器{
fn流程(&self,sig:&mut I)->Vec{
sig.map(| x | x*self.mul.collect())
}
}
用于Alg2的impl传感器滤波器{
fn流程(&self,sig:&mut I)->Vec{
sig.map(| x | x*self.add).collect()
}
}
枚举选择{
Alg1,
Alg2
}
fn main(){
let choice=AlgChoice::Alg1;//用户通过命令行进行选择。
让mut sig=vec![0,1,2,3,4,5,6.].进入_iter();//迭代器从传感器获取数据。
//指定trait的类型参数。
让alg:&dyn SensorFilter=匹配选项{
AlgChoice::Alg1=>&Alg1{mul:0.3},
_=>&Alg2{add:1.2},
};
让结果=分析过程(&mut sig);
println!(“{:?}”,结果);
}

这里的技巧是将通用函数参数更改为通用特性参数:

// Make the generic param into a type argument w/ constraints
trait SensorFilter<I> where I: Iterator<Item = f32> {
    fn process(&self, sig: &mut I) -> Vec<f32>;
}

struct Alg1 {
    mul: f32,
}

struct Alg2 {
    add: f32,
}

// Implement trait for all I that match the iterator constraint
impl<I: Iterator<Item = f32>> SensorFilter<I> for Alg1 {
    fn process(&self, sig: &mut I) -> Vec<f32> {
        sig.map(|x| x * self.mul).collect()
    }
}

impl<I: Iterator<Item = f32>> SensorFilter<I> for Alg2 {
    fn process(&self, sig: &mut I) -> Vec<f32> {
        sig.map(|x| x * self.add).collect()
    }
}

enum AlgChoice {
    Alg1,
    Alg2
}

fn main() {
    let choice = AlgChoice::Alg1; // user chooses via command-line.
    let mut sig = vec![0.,1.,2.,3.,4.,5.,6.].into_iter(); // iterator gets data from sensor.

    // Specify the type argument of your trait.
    let alg: &dyn SensorFilter<std::vec::IntoIter<f32>> = match choice {
        AlgChoice::Alg1 => &Alg1{mul:0.3},
        _ => &Alg2{add:1.2}, 
    };

    let result = alg.process(&mut sig);
    println!("{:?}",result);
}
//将泛型参数设置为带约束的类型参数
特征传感器过滤器,其中I:迭代器{
fn流程(&self,sig:&mut I)->Vec;
}
结构Alg1{
mul:f32,
}
结构Alg2{
地址:f32,
}
//为所有匹配迭代器约束的I实现trait
用于Alg1的impl传感器滤波器{
fn流程(&self,sig:&mut I)->Vec{
sig.map(| x | x*self.mul.collect())
}
}
用于Alg2的impl传感器滤波器{
fn流程(&self,sig:&mut I)->Vec{
sig.map(| x | x*self.add).collect()
}
}
枚举选择{
Alg1,
Alg2
}
fn main(){
let choice=AlgChoice::Alg1;//用户通过命令行进行选择。
让mut sig=vec![0,1,2,3,4,5,6.].进入_iter();//迭代器从传感器获取数据。
//指定trait的类型参数。
让alg:&dyn SensorFilter=匹配选项{
AlgChoice::Alg1=>&Alg1{mul:0.3},
_=>&Alg2{add:1.2},
};
让结果=分析过程(&mut sig);
println!(“{:?}”,结果);
}

使
传感器过滤器
对象安全的最简单方法是简单地将
过程
更改为接受
dyn迭代器
,而不是
impl迭代器

trait SensorFilter {
    fn process(&self, sig: &mut dyn Iterator<Item = f32>) -> Vec<f32>;
}

请注意,我没有使用
迭代器
,而是使用了
迭代器
,这是严格意义上更一般的

当您无法轻松地从
SensorFilter
中删除泛型时,这种想法的一种变体是使用双重分派:write
SensorFilter
使用
dyn迭代器而不是
impl迭代器
,然后编写一个方便的特性,用特定类型将其包装起来:

trait SensorFilter {
    fn process_dyn(&self, sig: &mut dyn Iterator<Item = f32>) -> Vec<f32>;
}

trait Process {
    fn process<I: IntoIterator<Item = f32>>(&self, sig: I) -> Vec<f32>;
}

impl<T: ?Sized + SensorFilter> Process for T {
    fn process<I: IntoIterator<Item = f32>>(&self, sig: I) -> Vec<f32> {
        self.process_dyn(&mut sig.into_iter())
    }
}
trait传感器过滤器{
fn进程(self,sig:&mutdyn迭代器)->Vec;
}
性状过程{
fn过程(&self,sig:I)->Vec;
}
T的impl过程{
fn流程(&self,sig:I)->Vec{
自处理(将信号转换为iter())
}
}

使
传感器过滤器
对象安全的最简单方法是简单地将
过程
更改为接受
dyn迭代器
,而不是
impl迭代器

trait SensorFilter {
    fn process(&self, sig: &mut dyn Iterator<Item = f32>) -> Vec<f32>;
}

请注意,我没有使用
迭代器
,而是使用了
迭代器
,这是严格意义上更一般的

当您无法轻松地从
SensorFilter
中删除泛型时,这种想法的一种变体是使用双重分派:write
SensorFilter
使用
dyn迭代器而不是
impl迭代器
,然后编写一个方便的特性,用特定类型将其包装起来:

trait SensorFilter {
    fn process_dyn(&self, sig: &mut dyn Iterator<Item = f32>) -> Vec<f32>;
}

trait Process {
    fn process<I: IntoIterator<Item = f32>>(&self, sig: I) -> Vec<f32>;
}

impl<T: ?Sized + SensorFilter> Process for T {
    fn process<I: IntoIterator<Item = f32>>(&self, sig: I) -> Vec<f32> {
        self.process_dyn(&mut sig.into_iter())
    }
}
trait传感器过滤器{
fn进程(self,sig:&mutdyn迭代器)->Vec;
}
性状过程{
fn过程(&self,sig:I)->Vec;
}
T的impl过程{
fn流程(&self,sig:I)->Vec{
自处理(将信号转换为iter())
}
}