Hiding infectious generics

I'm working on a wrapper for something that has an optional .. thing, that [when pulled in] requires generics. Sort of like this:

pub struct Thing<T> {
  ot: Option<OtherThing<T>>
}

impl<T> Thing<T> {
  pub fn use_otherthing(&mut self, ot: OtherThing<T>) {
  }
}


pub struct OtherThing<T> {
}

impl<T> OtherThing<T> {
}

The only reason Thing has <T> is because of the potential use of OtherThing.

For cases where the developer has no interest in using the OtherThing feature -- what constructs are there to "hide" the T in Thing? Is setting a default (<T = ()>) the best (only?) option?

For a fixed set of tasks T needs to be able to do, you can sometimes use type erasure and store a Box<dyn DoOtherThingTasks>.

For a fixed set of types that T may take on, you can use an enum (or sometimes type erasure).

2 Likes

An enum might be easier

If not using OtherThing is an expected common case, then I'd suggest splitting your struct into two separate types: one which doesn't include OtherThing and thus has no generic parameters, and one that does. You'd probably need to delegate some common methods from the former to the latter, but it shouldn't require too much boilerplate. Alternatively, ThingWithOtherThing could include ThingNoOtherThing as a field. Depending on your use case, this thing can be public, or perhaps you provide a conversion or getter for that field.

It's hard to tell from such an abstract example, but I'd go with the default type only if there is one that makes sense and if OtherThing is so intimately tied that it would be cumbersome to split Thing. Otherwise, I'd also be inclined to split Thing if it's used at a single place, e.g. if having two types is manageable.

Do you use Option<> only because the type is optional, or because ot is optional even when OtherThing is used? If it's the former and you decide to use the default type approach, you can simply make an empty default implementation of use_otherthing like in your example and remove Option. But it really depends how you intend to use it.