自动为已满足trait的类型实现该trait

5

TL;DR. 如果现有类型已经拥有了trait所需的所有方法,那么是否可以自动地为该类型实现一个trait?

详细版本。 假设我想要一个通用函数,可以在任何类似栈的类型上执行堆栈操作。因此,我有一个trait。

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

现在我可以像这样使用它:pub fn foo(s: &mut dyn StackLike<i32>) { s.push(42); }。 到此为止一切顺利。

已有几种类型已经满足了我的特性,因此实现它很容易,例如:

impl<T> StackLike<T> for Vec<T> {
    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, const N: usize> StackLike<T> for SmallVec<[T; N]> {
    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) }
}

这个方法是可行的,但需要写很多模板代码。在这里没有任何有趣的内容:方法名、参数类型和返回类型 - 一切都是一样的。

问题。是否有可能避免拼出所有这些重复的陈述,即像下面的代码片段那样做一些事情?

#[implement-trait-automagically]
impl<T> StackLike<T> for Vec<T>;

#[implement-trait-automagically]
impl<T, const N: usize> StackLike<T> for SmallVec<[T; N]>;

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

1个回答

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!(); }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接