如何将多个特质结合成为“特质元组”?

3
我编写了一个类库,如下所示:
struct Foo<A: AppleTrait, B: BananaTrait, C: CarrotTrait> {...}

impl<A: AppleTrait, B: BananaTrait, C: CarrotTrait> Foo<A,B,C> {...}

struct Bar<A: AppleTrait, B: BananaTrait, C: CarrotTrait> {...}

impl<A: AppleTrait, B: BananaTrait, C: CarrotTrait> Bar<A,B,C> {...}

... and many more...

请注意,像 <A: AppleTrait, B: BananaTrait, C: CarrotTrait> 这样的东西总是一起出现,而且出现了很多次。因此,我希望能够消除这种负担。

因此,我希望能做一些类似于以下的事情:

define_the_trait_alias ABCTrait = (A: AppleTrait, B: BananaTrait, C: CarrotTrait); // How to do this?

struct Foo<ABC: ABCTrait> {...}

impl<ABC: ABCTrait> Foo<ABC> {...}

感谢!

你可以通过在不需要的地方省略边界来消除很多冗余。请参见(特别是我的回答)Should trait bounds be duplicated in struct and impl? - trent
@trentcl 感谢!但即使省略掉,它仍然有点长 :/ - ch271828n
2个回答

5

也许你可以使用关联类型而不是泛型。例如:

trait AbcTrait {
    type Apple: AppleTrait;
    type Banana: BananaTrait;
    type Carrot: CarrotTrait;
}

struct Foo<Abc: AbcTrait> {
    abc: Abc,
}
impl<Abc: AbcTrait> Foo<Abc> {}

struct Bar<Abc: AbcTrait> {
    abc: Abc,
}
impl<Abc: AbcTrait> Bar<Abc> {}

当定义一个trait的具体实现时,您可以选择哪个具体类型实现了trait所请求的关联类型:

impl AbcTrait for Salad {
    type Apple = GrannySmith;
    type Banana = Cavendish;
    type Carrot = LunarWhite;
}

4
您可以创建一个超级特性(super-trait),将ABC作为相关类型(associated types)。 然后,您实现该特性以供 (A,B,C) 使用,并在需要指定类型时使用它,例如:some_func_that_takes_type_params::<(StructA, StructB, StructC)>()。 要访问ABC,请改用相关类型。
trait SuperTrait{
    type A: AppleTrait;
    type B: BananaTrait;
    type C: CarrotTrait;
}
impl<A: AppleTrait, B: BananaTrait, C: CarrotTrait> SuperTrait for (A,B,C)
{
    type A = A;
    type B = B;
    type C = C;
}

struct Foo<D: SuperTrait> (std::marker::PhantomData<D>);

impl<D: SuperTrait> Foo<D> {
    /// Example function that returns an A
    fn return_a(&self) -> D::A{
        todo!()
    }
}

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