如何创建包含特征的泛型类型

pm1*_*100 7 rust

我发现我经常使用这种模式。

Arc<Mutex<dyn SomeTrait + Send>>;
Run Code Online (Sandbox Code Playgroud)

所以我想我会这样做:

pub type NicePtr<T> = Arc<Mutex<dyn T + Send>>;
Run Code Online (Sandbox Code Playgroud)

但这不能编译

   Compiling rsim v0.1.0 (C:\work\pdp\rsim)
error[E0404]: expected trait, found type parameter `T`
 --> src\common.rs:9:37
  |
9 | pub type NicePtr<T> = Arc<Mutex<dyn T + Send>>;
  |                                     ^ not a trait
Run Code Online (Sandbox Code Playgroud)

我认为这是可能的,但我只是不知道正确的语法。

ask*_*sky 0

正如评论指出的那样,您可以使用宏完成与您想要的类似的事情。您可以拥有一个扩展为一种类型的宏和一个包装宏Arc::new(Mutex::new())(或您认为合适的任何其他指针类型)。

use std::sync::{Arc, Mutex};
use std::fmt::Display;

macro_rules! nice_ptr {
    // for types
    ($t:ty) => {
        Arc<Mutex<$t>>
    };
    // for traits
    ($t:expr) => {
        Arc<Mutex<$t>>
    }
}

macro_rules! nice_ptr_new{
    ($inner:expr) => {
        Arc::new(Mutex::new($inner))
    }
}

fn main() {
    let example: nice_ptr!(dyn Display) = nice_ptr_new!("example");
    println!("{}", example.lock().unwrap());
}
Run Code Online (Sandbox Code Playgroud)

将其与错误的类型一起使用甚至会给出有用的错误消息。

fn main() {
    // arrays don't implement Display!
    let example: nice_ptr!(dyn Display) = nice_ptr_new!([1,2,3]);
    println!("{}", example.lock().unwrap());
}
Run Code Online (Sandbox Code Playgroud)
15 |         Arc::new(Mutex::new($inner))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `[{integer}; 3]` cannot be formatted with the default formatter
...
20 |     let example: nice_ptr!(dyn Display) = nice_ptr_new!([1,2,3]);
   |                                           ---------------------- in this macro invocation
   |
   = help: the trait `std::fmt::Display` is not implemented for `[{integer}; 3]`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: required for the cast to the object type `dyn std::fmt::Display`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)