C++ Container equivalents

Downs default_357-line at yahoo.de
Tue Aug 14 23:36:40 PDT 2007


Bruce Adams wrote:
> Most of the time D arrays should be enough. In C++ I end up using
> vector, map and set the most. The set is the main one I want
> to identify an equivalent to.

This is kind of embarrassing, because there's no such thing as sets in
D, natively. The closest you can come is probably bool[Type], that is,
an associative array.

Regarding lists, here's a proto-implementation I threw together.
Basic functionality is missing, but you should get the idea. The actual
struct is Phobos/Tango-agnostic.
Have fun!
 --downs


struct list(T) {
  private {
    static struct entry {
      T value=void;
      entry *next=null, prev=null;
    }
    entry *first=null, last=null;
    void update(bool left)(entry *e, entry *newEntry) {
      static if(left) {
        if (e==first) first=newEntry;
        else { e.prev.next=newEntry; newEntry.prev=e.prev; }
      } else {
        if (e==last) last=newEntry;
        else { e.next.prev=newEntry; newEntry.next=e.next; }
      }
      // at this point we have effectively removed e.
      // but we keep it around to prevent the GC from wailing in anguish
      // delete e;
    }
  }
  static list opCall(T[] init) {
    list res;
    foreach (entry; init) res.push_back(entry);
    return res;
  }
  static list opCall(entry *a, entry *b) { list res=void; res.first=a;
res.last=b; return res; }
  void push(bool front)(T what) {
    auto newEntry=new entry;
    newEntry.value=what;
    static if (front) {
      if (first) { newEntry.next=first; first.prev=newEntry; }
first=newEntry;
      if (!last) last=first;
    }
    else {
      if (last) { newEntry.prev=last; last.next=newEntry; } last=newEntry;
      if (!first) first=last;
    }
  }
  bool opEquals(T[] comp) {
    size_t count=0;
    foreach (entry; *this) {
      if (count==comp.length) return false;
      if (comp[count++]!=entry) return false;
    }
    if (count!=comp.length) return false;
    return true;
  }
  list opSlice(size_t from, size_t to) {
    entry *start=first; while (from--) { start=start.next; to--; }
    entry *end=start; while (--to) end=end.next;
    return list(start, end);
  }
  void opSliceAssign(list what, size_t from, size_t to) {
    entry *start=first; while (from--) { start=start.next; to--; }
    entry *end=start; while (--to) end=end.next;
    update!(true)(start, what.first);
    update!(false)(end, what.last);
  }
  int opApply(int delegate(ref T) dg) {
    entry *current=first;
    writefln("_____");
    scope(exit) writefln("'''''");
    while (true) {
      writefln("Entry ", current.value);
      auto res=dg(current.value);
      if (res) return res;
      if (current==last) return 0;
      current=current.next;
    }
  }
  int opApply(int delegate(ref size_t, ref T) dg) {
    size_t count=0;
    foreach (ref entry; *this) { auto res=dg(count, entry); ++count; if
(res) return res; }
    return 0;
  }
  alias push!(true) push_front; alias push!(false) push_back;
  size_t length() { size_t res=0; foreach (bogus; *this) ++res; return
res; }
  T[] toArray() { auto res=new T[length]; foreach (id, entry; *this)
res[id]=entry; return res; }
}

import std.stdio;
void main() {
  list!(int) test;
  test.push_back(5);
  test.push_front(4);
  test.push_back(8);
  writefln(test.toArray);
  assert(test==[4, 5, 8]);
  writefln(test[1..2].toArray);
  assert(test[1..2]==[5]);
  test[1..2]=list!(int)([6, 7]);
  writefln(test.toArray);
  assert(test==[4, 6, 7, 8]);
}


More information about the Digitalmars-d-learn mailing list