ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.1k stars 441 forks source link

Interleaved Range #221

Open AdamSpeight2008 opened 8 years ago

AdamSpeight2008 commented 8 years ago

In C# you could do something along the lines of this.

IEnumerable<T> Interleave<T> (ICollection<IEnumerable<T>> xs )
{
  if( ( xs == null ) || ( xs.Count == 0 ) ) return;
  using (var nx = new CircularLinkedList<T>() )
  { 
    // Generate a circular linked list of containing the enumerated enumerators.
    using( var en0 = xs.GetEnumerator() )
    {
      while ( en.MoveNext() )
      {
        nx.AddLast( en.Current.GetEnumerator() ) ; // Add this enumerator to circular linked list.
      };

    } // Dispose of the enumerator, used to get the enumerators.

    while( nx.Any() )           // Are there a nodes to process?
    {
      var en = nx.Head;
      if( en.Value.MoveNext() ) // is there a next value?
      {
        yield en.Value.Current; // yield the current value, of the current enumerator ( en )
        nx.RotateLeft();        // eg Move Head to Head.Next
      }
      else
      {
        en.Value.Dipose();     // dispose of the enumerator (Note T needs to be constrained T:IDisposable )
        en.Remove();           // remove this node
      }
    }
  } // dispose of the circular linked list.
}
CaseyCarter commented 8 years ago

For bonus points: the value type of this range should be the common type of the value types of the interleaved ranges when such a common type exists, and otherwise a variant of the value types of the interleaved ranges. For more bonus points, reuse the variant-iterator to implement the (probably useless) tuple_range which iterates over the fields of a tuple. variant-iterator's reference type must of course be a variant of the reference types of the iterators of the interleaved ranges.

Taken to unnecessary extremes, this has the potential to be as complex as zip iterators.

ericniebler commented 8 years ago

For bonus points: the value type of this range should be the common type of the value types of the interleaved ranges when such a common type exists

And the reference type should be the common reference.

and otherwise a variant of the value types of the interleaved ranges.

I don't like. It's surprising. You shouldn't be able to interleave ranges if they don't have compatible reference/value types.

gnzlbg commented 8 years ago

You shouldn't be able to interleave ranges if they don't have compatible reference/value types.

any_view is open, but a closed variant-like one might help here and in other places (concatenating two ranges of two completely different value types).

CaseyCarter commented 8 years ago

I don't like. It's surprising.

variant<T, U> is a common type of T and U. If it's sound to present a composition of heterogeneous ranges of T and U as a range of common_type_t<T, U>, then it is equally sound to present a composition of heterogeneous ranges of T and U as a range of variant<T, U>. I'm not advocating that this notion that popped into my head and I've given no real consideration is a magic bullet for heterogeneous ranges that we should rush to get it into the TS, but it's at least interesting as a thought experiment.

ericniebler commented 8 years ago

If it's sound to present a composition of heterogeneous ranges of T and U as a range of common_type_t<T, U>, then it is equally sound to present a composition of heterogeneous ranges of T and U as a range of variant<T, U>.

No. The difference is that common_iterator is an iterator. It is usable and has behavior that is a subset of the wrapped iterator's behavior. A variant is not that. It's a generally useless bag-o-bits with no interface in common with the types it wraps. variant is not a meaningful common type, IMO.