简体   繁体   中英

Implementing a trait that has associated trait types

I'm having trouble learning about associated types. My problem code:

trait Fooer {
    fn foo(&self);
}

trait FooStore {
    type T: Fooer;
    fn store_foo(&self, fooer: Self::T);
}

#[allow(dead_code)]
struct DB {}

impl FooStore for DB {
    type T = Fooer;

    fn store_foo(&self, _fooer: Self::T) {}
}

fn main() {}

Play link

The intent here is to use associated types to make the FooStore trait not require the awkward and problematic syntax of impl<F:Fooer, T: FooStore<F>> FooStore<F> for DB because that often complains about F not being used.

However, the official docs on this feature show objects implementing the underlying associated type - but not traits. In this example, DB does not know what structs might be passed into store_foo(..) , so it needs to use a trait to solve this issue.

With that said, how can I get an associated type to use a trait during impl ? That is, how can I write type T = Fooer; ? Or am I using this wrong somehow?

Note : I'm having some trouble constructing this example, I'm trying to correct this now. The error I was having is:

cargo: the trait `Fooer` cannot be made into an object [E0038]

The intent here is to use associated types to make the FooStore trait not require the awkward and problematic syntax of impl<F:Fooer, T: FooStore<F>> FooStore<F> for DB because that often complains about F not being used.

Your struct DB needs to assign a concrete type that implements Fooer to FooStore::T . Fooer is a trait, but can also be used as an unsized type. However, you can't use an unsized type here, because you can't pass an argument of an unsized type by value (which FooStore::store_foo requires).

If you don't want DB to assign a particular type to FooStore::T , then you can make DB generic.

use std::marker::PhantomData;

#[allow(dead_code)]
struct DB<F: Fooer> {
    _phantom: PhantomData<F>,
}

impl<F: Fooer> FooStore for DB<F> {
    type T = F;

    fn store_foo(&self, _fooer: Self::T) {}
}

Notice the use of PhantomData : we use it to force the parameter T to be used, and it also indicates that DB<T> conceptually owns objects of type T .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM