The general feature is usually referred to as enum impl Trait
(sometimes enum dyn Trait
).
That said, this sort of delegation is quite complicated to generalize beyond specific traits; see the recent RFC#3367 for a discussion on that long tail. "Delegation safety" is related to dyn/object safety, except that presumably your impl Trait
is Sized
, so it also has any non-object-safe trait members guarded by where Self: Sized
.
Because of this, I could actually see std providing some sort of iter::Select
combinator, as a kind of dual to iter::Chain
. The interesting/difficult part is actually specifying what the stable interface should look like.
If you have a reasonably minimal API surface proposal, it'd be a reasonable fit for an ACP (basically a lighter weight RFC for pure library API additions). Here on IRLO is also a decent place to draft such.
Only .either()
can't work, though: it only ever produces the "Either::Left
" version. The minimal API surface will (modulo naming bikeshed) look something along the lines of
// mod ::core::iter
struct Select<A, B> { /* private fields */ }
impl<A, B> Iterator for Select<A, B>
where
A: Iterator,
B: Iterator<Item = <A as Iterator>::Item>,
{
type Item = <A as Iterator>::Item;
/* method implementation */
}
// plus other common traits; see Chain for a template
fn select_first<A, B>(a: A) -> Select<A, B>;
fn select_second<A, B>(b: B) -> Select<A, B>;
...although, now that I'm thinking about it, an alternative entry point could be
impl<T> Option<T> {
fn unwrap_iter_or_else<U, F>(self, f: F) -> iter::Select<T, U>
where F: FnOnce() -> U
{
match self {
Some(a) => iter::select_first(a),
None => iter::select_second(f()),
}
}
}
playing into the Flatten<Chain<Option<A>, Option<B>>>
perspective, but naming that method is even harder, and any closure-based solution runs into the "mutex closure" problem where only one or the other can capture exclusive state, despite external knowledge only one closure will run, thus requiring the Option::take
workaround to runtime encode that knowledge. So stick to the two separate constructors.