These thoughts were inspired by the recent thread, "Retrieving the 
traversed range". I am generally pretty sold on the range concept, 
but I think for some operations some sort of cursor is required. 
However, there are some unsafe cursor-related operations that are
best avoided. 

However, as far as I can see, the unsafe operations revolve around
synthesizing a new range out of two cursors. However, you can get 
a lot of the desired functionality associated with finding elements and
splitting ranges *without* allowing the synthesis of of ranges from
unrelated cursors. The key to doing this is to have each cursor be permanently 
bound to the underlying range which it was derived from.

If you have this kind of cursor, you only really need it to support two 
operations to get a huge amount of benefit:

     Range before ();

     Range after ();

The before () operation just returns a range of the appropriate type (Forward, 
Bidirectional, RandomAccess) of all the elements that come before the cursor is 
pointing to, while the after () operation returns a range of the appropriate 
type with all the elements after the cursor. Given this concept, a cursor 
really points at the boundary between elements of a range, if you will.

If find and related operations return this kind of cursor, all of the 
operations involving splitting ranges become trivial. It's completely 
consistent for either before () or after () to be empty, and since you can't 
glue two of these cursors together, you are always guaranteed to get 
well-defined ranges out. 

While I think the before () and after () operations are the only ones 
which are strictly necessary for the desiderata I've seen so far, people 
could write their own generic algorithms if cursors supported more of 
the iterator operations, for moving forward (and backward, where appropriate) 
and inspecting the element immediately after the cursor (or before, where 
appropriate), and if ranges supported operations to return cursors from 
reasonable places (like from the front or back, or from a specific indexed 
elemnt for RandomAccess ranges).

The key idea is that these cursors aren't a primitive part of a range; instead, 
they take a range and add a position *inside* the range. They're a perfect fit 
for all those "three-legged" operations out there because they actually have 
three legs.

Cheers,
Pillsy

Reply via email to