range properties that work in foreach
Michael Rynn
michaelrynn at optusnet.com.au
Sat Mar 6 03:01:37 PST 2010
On the D2 online pages
(http://www.digitalmars.com/d/2.0/statement.html#ForeachStatement)there
is
Foreach over Structs and Classes with Ranges
My question is , is there a working example of foreach ( e ; range )?
Iteration over struct and class objects can be done with ranges, which
means the following properties must be defined:
Property Purpose
.empty returns true if no more elements
.next move the left edge of the range right one
.retreat move the right edge of the range left one
.head return the leftmost element of the range
.toe return the rightmost element of the range
So I tried this , but foreach did not work, but using
the equivalent for loop code did.
List test;
/// this worked
for (auto __r = list.range ; !__r.empty; __r.next)
{ auto e = __r.head;
...
}
/// this didn't
foreach( e ; list.range (
Below is the template code , which otherwise worked.
Since I have had no advantage to using names head, toe, next, retreat
(are these still supposedly the names to use? "retreat" is a strange
one. Perhaps "runaway" would be better. ) I changed them. to front,
back, popFront, popBack.
struct linkrange(P) {
P left_;
P right_;
this(P n)
{
left_ = n;
right_ = (n !is null) ? n.prev_ : null;
}
/// Range property
@property bool empty()
{
return (left_ is null);
}
/// Range property
@property P front()
{
return left_;
}
/// Range property
@property P back()
{
return right_;
}
/// Range function
@property void popFront()
{
if (left_ == right_)
{
left_ = null;
right_ = null;
}
else
left_ = left_.next_;
}
/// Range function
@property void popBack()
{
if (right_ == left_)
{
left_ = null;
right_ = null;
}
else
right_ = right_.prev_;
}
}
/// Embed this to provide the linked list manager.
struct linklist(P) {
P head_;
size_t linkct_;
void clear()
{
head_ = null;
linkct_ = 0;
}
ref linklist opAssign(ref linklist K)
{
head_ = K.head_;
linkct_ = K.linkct_;
return this;
}
@property
bool empty()
{
return (head_ is null);
}
@property
linkrange!(P) range()
{
return linkrange!(P)(head_);
}
@property P front()
{
return head_;
}
@property size_t length()
{
return linkct_;
}
private void linkFirst(P n)
{
head_ = n;
n.next_ = n;
n.prev_ = n;
}
private void linkBefore(P n, P f)
{
P last = f.prev_;
n.next_ = f;
n.prev_ = last;
f.prev_ = n;
last.next_ = n;
linkct_++;
}
void putBack(P n)
{
if (head_ !is null)
linkBefore(n, head_);
else
linkFirst(n);
}
void putFront(P n)
{
if (head_ !is null)
{
linkBefore(n, head_);
head_ = n;
}
else{
linkFirst(n);
}
}
void popBack()
{
remove(head_.prev_);
}
void popFront()
{
remove(head_);
}
void remove(P n)
{
if (n == head_)
{
P test = n.next_;
head_ = (head_ != test) ? test : null;
}
n.unlink();
}
}
/// mixin this to provide the links.
/// A more advanced template might provide field naming suffix.
template links(P)
{
P prev_;
P next_;
void unlink()
{
prev_.next_ = next_;
next_.prev_ = prev_;
next_ = null;
prev_ = null;
}
}
/// A linked list without embedding the pointers inside the object.
struct QueueList(P) {
alias QElem* QElemPtr;
struct QElem {
this(P val)
{
value = val;
}
P value;
mixin links!(QElemPtr);
}
linklist!(QElemPtr) nodes;
@property
bool empty()
{
return nodes.empty;
}
@property
P front()
{
return nodes.front.value;
}
void putFront(P val)
{
QElem* e = new QElem(val);
nodes.putFront(e);
}
void putBack(P val)
{
QElem* e = new QElem(val);
nodes.putBack(e);
}
void popFront()
{
nodes.popFront();
}
}
More information about the Digitalmars-d-learn
mailing list