【问题标题】:Is there a way to impl trait for a tuple that may have any number elements? [duplicate]有没有办法为可能有任何数量元素的元组实现特征? [复制]
【发布时间】:2020-06-26 03:12:02
【问题描述】:

我有这样的特质:

trait Foo {
    fn do_something(self) -> Self;
}

我想为一个元组实现这个特征,它可能有任意数量的元素来实现这个特征。

impl<T> Foo for (T, T) where T: Foo {
    fn do_something(self) -> Self {
        let (t0, t1) = self;
        (t0.do_something(), t1.do_something())
    }
}

impl<T> Foo for (T, T, T) where T: Foo {
    fn do_something(self) -> Self {
        let (t0, t1, t2) = self;
        (t0.do_something(), t1.do_something(), t2.do_something())
    }
}

// and so on...

【问题讨论】:

标签: rust


【解决方案1】:

注意:我不确定您是否应该这样做,但无论如何这里有一个方法。 (我觉得很hacky,这可能是因为我不知道如何制作更好的宏。)

同构元组(T, T)

你描述的方式:

impl&lt;T&gt; Foo for (T, T) where T: Foo

这里,整个元组必须是同质的(即(MyType, MyType2).do_something()工作,因为单态化)。 这会引发一个标志,因为元组用于异构数据。

如果只实现一个同构元组的特征仍然是您想要的,我们可以通过the standard library does to implement traits for varied length tuples 的方式实现一个宏,并进行一些修改。 (点击impl右侧的src查看其来源。)

macro_rules! replace_expr {
    ($_t:tt $sub:ty) => {$sub};
}

macro_rules! tuple_impls {
    ( $( $name:ident )+ ) => {
        impl<T: Foo> Foo for ($(replace_expr!(($name) T),)+)
        {
            fn do_something(self) -> Self {
                let ($($name,)+) = self;
                ($($name.do_something(),)+)
            }
        }
    };
}

tuple_impls! { A }
tuple_impls! { A B }
tuple_impls! { A B C }
tuple_impls! { A B C D }
tuple_impls! { A B C D E }
tuple_impls! { A B C D E F }
tuple_impls! { A B C D E F G }
tuple_impls! { A B C D E F G H }
tuple_impls! { A B C D E F G H I }
tuple_impls! { A B C D E F G H I J }
tuple_impls! { A B C D E F G H I J K }
tuple_impls! { A B C D E F G H I J K L }

Playground

异构元组(T1, T2)

如果你对 (MyType, MyType2).do_something() 工作没问题(两者都实现了 Foo 特征),你可以试试这个更简单的宏:

macro_rules! tuple_impls {
    ( $( $name:ident )+ ) => {
        impl<$($name: Foo),+> Foo for ($($name,)+)
        {
            fn do_something(self) -> Self {
                let ($($name,)+) = self;
                ($($name.do_something(),)+)
            }
        }
    };
}

tuple_impls! { A }
tuple_impls! { A B }
tuple_impls! { A B C }
tuple_impls! { A B C D }
tuple_impls! { A B C D E }
tuple_impls! { A B C D E F }
tuple_impls! { A B C D E F G }
tuple_impls! { A B C D E F G H }
tuple_impls! { A B C D E F G H I }
tuple_impls! { A B C D E F G H I J }
tuple_impls! { A B C D E F G H I J K }
tuple_impls! { A B C D E F G H I J K L }

Playground

【讨论】:

  • 不,使用数组。
【解决方案2】:

没有。 (除非您准备好使用宏 - 请参阅其他答案)

Rust 中的元组具有固定长度 just like arrays。我不相信你可以表达“任何长度的元组”的概念。

换句话说,包含 2 个元素的元组与包含 3 个元素的元组是不同的复合类型。如果您坚持使用元组,则必须采用上述解决方案。

使用集合? (例如给现有的一个别名并在其上实现特征)?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2019-11-08
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多