Many toolkit authors create their own string types instead of using
std::string. This includes the likes of Qt and FOX. My question, and
perhaps it is not topical, is why would people do this? They also don't
provide conversion functions to/from std::string! This makes it so you
are always converting to/from std::string yourself to communicate with
these APIs. Very annoying.
std::string isn't one of the better parts of the standard library, IMHO.
Speaking of which, I started writing prototype of linked-list using Knuth's
single-pointer double-linked list technique, I decided to implement it as
std::list<> -lookalike, here's URL for work-in-process version (it won't
compile w/o metatype.hpp -header, which defines couple of templates and
types, and macros, but the idea should be fairly clear to read ;)
www.liimatta.org/misc/list.hpp
... and "screenshot" of a small test:
www.liimatta.org/misc/list.jpg
I haven't really kept thread safety in mind, just want to try out the
concept.. so far it appears to be a solid idea. Also get iterator,
const_iterator, reverse_iterator and const_reverse_iterator with same
template as by-product, less maintenance overhead. I don't throw exceptions
either, where std::list might (I haven't looked at the problem from this
angle), so that could explain the speed differences. I am testing in release
build and the count is 200K in the list.jpg.
There are a few design choises I am not completely happy about, but they are
trade-offs between speed in different areas. First Issue:
the ::begin(), ::end(), etc. return iterators of various types, it would be
advantageous to cache the step values so that they don't need to be
re-computed, however, the re-computation is only two bitwise xor's so I
think that optimization would be defeated when maintenance overhead would
attack all other more frequently called methods. This is "problem" only in
situation such as this:
list<int>::iterator i = v.begin();
for ( ; i != v.end(); ++i )
;
So it would be advantageous to cache the v.end(), unless we write into the
container.. etc..
Second Issue is that -- operator must step twice, first to get into the next
node, to get new source.. then step over current node to reversed direction,
so it's two xor's instead of one. Could cache the source -and- destination
pointers, and when --'ing, step to get "new destination", write current to
temp, write destination into current, and write current to source.
But again, the maintenance overhead would kick in, and the backwards
stepping is still virtually same speed as stepping "ahead" (++), so prefer
it the way it is. But that did bear mentioning. :)
"ahead" (++) and "backwards" (--) are relative concept in this
implementation, as the direction is determined by the current state of the
iterator (it cannot be switched in-flight, only when iterator is created,
this way the reverse_iterator stays reverse_iterator and iterator remains
iterator regardless of what the client does. I will propably add bool
template parameter to formally enforce the difference between the two, so
don't need criticism for that-- consider it being in the TODO -list.
I hope I got the semantics nailed down correctly, criticism is welcome, you
seem ideal candidate to flame the implementation: :) :)
-w