任何由实现该trait的类型组成的元组,是否可以自动实现该trait?

6

假设我有一个

trait Happy {}

我可以为任何我想要的结构体实现Happy,例如:

struct Dog;
struct Cat;
struct Alligator;

impl Happy for Dog {}
impl Happy for Cat {}
impl Happy for Alligator {}

现在,我想自动实现对任何由所有实现“Happy”trait的类型组成的元组进行我的“Happy”trait。直观地说,全部为happy的元组也是happy的。
这样做可能吗?例如,我可以轻松地将“Happy”的实现扩展到任意两个“Happy”类型的元组:
impl <T, Q> Happy for (T, Q) where T: Happy, Q: Happy {}

因此,这段代码可以完美地编译:

fn f(_: impl Happy) {
}

fn main() {
    f((Dog{}, Alligator{}));
}

但是我如何将其推广到任何长度的元组呢?据我所知,Rust 中没有变长泛型。是否有解决方法?


1
宏。这就是目前的做法。 - Boiethios
1
我不确定是否可能。即使标准库也必须为每个可能的元组长度提供实现,最多达到12个。 - ForceBru
1个回答

10
我们在Rust中没有可变泛型参数。{{正确}}。
有解决方法吗?
你可以使用宏:{{你使用宏。}}
trait Happy {}

macro_rules! tuple_impls {
    ( $head:ident, $( $tail:ident, )* ) => {
        impl<$head, $( $tail ),*> Happy for ($head, $( $tail ),*)
        where
            $head: Happy,
            $( $tail: Happy ),*
        {
            // interesting delegation here, as needed
        }

        tuple_impls!($( $tail, )*);
    };

    () => {};
}

tuple_impls!(A, B, C, D, E, F, G, H, I, J,);

现在这个可以编译:

fn example<T: Happy>() {}

fn call<A: Happy, B: Happy>() {
    example::<(A, B)>();
} 

这通常不被视为一个大问题,因为长元组基本上是难以阅读的,如果真的需要,你总是可以嵌套元组。
另请参见:
- 自动实现 Rust 新类型(只有一个字段的元组结构)的封闭类型特征 - 如何迭代或映射元组?

只是想指出,虽然习惯上为(A, ) + (A, B) + (A, B, C)实现Trait,但这个答案将会为(A, B, C) + (B, C) + (C, )等实现它,即它递归地弹出第一个字母而不是最后一个。语义上,这与通常的行为相同,但在rustdocvscode类型提示和/或其他取决于您的设置的地方可能会有所不同。 - cutsoy

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