简体   繁体   English

如何将通用 T 发送到另一个线程?

[英]How to send generic T to another thread?

How to send generic T ?如何发送通用T

I try to send a generic T to another thread but I'm getting:我尝试将通用T发送到另一个线程,但我得到:

error[E0308]: mismatched types
  --> src/main.rs:23:22
   |
23 |             t1.merge(Element(vec![3]));
   |                      ^^^^^^^^^^^^^^^^ expected associated type, found struct `Element`
   |
   = note: expected associated type `<T as Join>::Item`
                       found struct `Element`
   = help: consider constraining the associated type `<T as Join>::Item` to `Element`

Full code:完整代码:

trait Join {
    type Item;
    fn merge(&mut self, other: Self::Item);
}

#[derive(Debug, Default)]
struct Element(Vec<u8>);

impl Join for Element {
    type Item = Element;
    fn merge(&mut self, mut other: Self::Item) {
        self.0.append(&mut other.0);
    }
}

fn work<T>()
where
    T: Default + Join + Send + Sync + 'static,
{
    let (sender, receiver) = std::sync::mpsc::channel::<(T)>();
    std::thread::spawn(move || {
        while let (mut t1) = receiver.recv().unwrap() {
            t1.merge(Element(vec![3]));
        }
    });

    loop {
        let mut t1 = T::default();
        sender.send(t1);
        std::thread::sleep(std::time::Duration::from_secs(5));
    }
}

fn main() {
    // works!
    let mut e = Element(vec![1]);
    e.merge(Element(vec![2]));

    // bad!
    work::<Element>();
}

Playground link 游乐场链接

When you use generics you let the caller decide which types must be used by your generic function.当您使用 generics 时,您让调用者决定您的通用 function 必须使用哪些类型。

This line in your example t1.merge(Element(vec;[3]));您的示例中的这一行t1.merge(Element(vec;[3])); is invalid because it assumes T = Element but the caller can chose from infinitely many possible types of T where T != Element which is why the compiler is complaining.是无效的,因为它假定T = Element但调用者可以从无限多种可能的T类型中进行选择,其中T != Element这就是编译器抱怨的原因。

To make your function fully generic you have to do something like add a Default bound to <T as Join>::Item in the function signature and then change the offending line to t1.merge(<T as Join>::Item::default());要使您的 function 完全通用,您必须执行一些操作,例如在 function 签名中添加Default绑定到<T as Join>::Item ,然后将违规行更改为t1.merge(<T as Join>::Item::default()); . .

Updated working commented example:更新的工作注释示例:

use std::fmt::Debug;

trait Join {
    type Item;
    fn merge(&mut self, other: Self::Item);
}

#[derive(Debug)]
struct Element(Vec<u8>);

// updated Default impl so we can observe merges
impl Default for Element {
    fn default() -> Self {
        Element(vec![1])
    }
}

impl Join for Element {
    type Item = Element;
    fn merge(&mut self, mut other: Self::Item) {
        self.0.append(&mut other.0);
    }
}

fn work<T>() -> Result<(), Box<dyn std::error::Error>>
where
    T: Default + Join + Send + Sync + Debug + 'static,
    <T as Join>::Item: Default, // added Default bound here
{
    let (sender, receiver) = std::sync::mpsc::channel::<T>();
    std::thread::spawn(move || {
        while let Ok(mut t1) = receiver.recv() {
            // changed this to use Default impl
            t1.merge(<T as Join>::Item::default());

            // prints "Element([1, 1])" three times
            println!("{:?}", t1);
        }
    });

    let mut iterations = 3;
    loop {
        let t1 = T::default();
        sender.send(t1)?;
        std::thread::sleep(std::time::Duration::from_millis(100));
        iterations -= 1;
        if iterations == 0 {
            break;
        }
    }

    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // works!
    let mut e = Element(vec![1]);
    e.merge(Element(vec![2]));

    // now also works!
    work::<Element>()?;

    Ok(())
}

playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM