自动为已经满足的类型实现特征

And*_*kin 5 rust

\n

TL;博士。是否可以为已经具有特征所需的所有方法的现有类型自动实现特征?

\n

长版。假设我想要一个通用函数,可以对任何类似堆栈的类型执行堆栈操作。所以我有一个特点

\n
pub trait StackLike<T> {\n    fn is_empty(&self) -> bool;\n    fn pop(&mut self) -> Option<T>;\n    fn push(&mut self, value: T);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我现在可以这样使用pub fn foo(s: &mut dyn StackLike<i32>) { s.push(42); }:到目前为止,一切都很好。

\n

有几种现有类型已经满足我的特征,因此实现它很简单,例如

\n
impl<T> StackLike<T> for Vec<T> {\n    fn is_empty(&self) -> bool { self.is_empty() }\n    fn pop(&mut self) -> Option<T> { self.pop() }\n    fn push(&mut self, value: T) { self.push(value) }\n}\n\nimpl<T, const N: usize> StackLike<T> for SmallVec<[T; N]> {\n    fn is_empty(&self) -> bool { self.is_empty() }\n    fn pop(&mut self) -> Option<T> { self.pop() }\n    fn push(&mut self, value: T) { self.push(value) }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这可行,但有很多样板。这里绝对没有发生任何有趣的事情:方法名称、参数类型和返回类型 \xe2\x80\x94 一切都相同。

\n

问题。是否可以避免拼写出所有这些同义反复的陈述,即执行类似于下面的代码片段的操作?

\n
#[implement-trait-automagically]\nimpl<T> StackLike<T> for Vec<T>;\n\n#[implement-trait-automagically]\nimpl<T, const N: usize> StackLike<T> for SmallVec<[T; N]>;\n
Run Code Online (Sandbox Code Playgroud)\n

或者我可以以某种方式标记我的特征,以便所有可以满足的类型自动满足它(类似于概念在 C++ 中的工作方式)?

\n

cdh*_*wie 10

Rust 没有这种“鸭子类型”,但您可以将实现放在宏后面,以实现您既定的目标,即避免所有样板代码,同时保持实现相同且无错误:

pub trait StackLike<T> {
    fn is_empty(&self) -> bool;
    fn pop(&mut self) -> Option<T>;
    fn push(&mut self, value: T);
}

macro_rules! stacklike_impl {
    () => {
        fn is_empty(&self) -> bool { self.is_empty() }
        fn pop(&mut self) -> Option<T> { self.pop() }
        fn push(&mut self, value: T) { self.push(value) }
    }
}

impl<T> StackLike<T> for Vec<T> { stacklike_impl!(); }
impl<T, const N: usize> StackLike<T> for SmallVec<[T; N]> { stacklike_impl!(); }
Run Code Online (Sandbox Code Playgroud)