first commit
This commit is contained in:
368
extern/ustl/1.5/docs/ChangeLog
vendored
Normal file
368
extern/ustl/1.5/docs/ChangeLog
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
2011-03-16 Release 1.5
|
||||
* Updated set, map, and multimap with full set of insert, erase, and search overloads
|
||||
* Added public lower_bound, upper_bound, and equal_range to map, as per standard
|
||||
* Added comparator parameter to set, multiset, map, and multimap.
|
||||
* Implemented FirstBit, Rol, Ror, and a generic NextPow2
|
||||
* Remove memlink copy because it conflicts with string copy
|
||||
* Operators returning a new value should be const
|
||||
* Added char* + string operator, and a noarg erase
|
||||
* Added --force-inline configure option
|
||||
* Removed all references to stdc++ headers when not using libstdc++
|
||||
* Fixed minor glitches compiling with clang++
|
||||
* Other small fixes
|
||||
|
||||
2010-03-21 Release 1.4
|
||||
* Fixed crash in destructor of empty vector, introduced by 1.3
|
||||
* Fixed list merge, which previously did not compile
|
||||
* Some portability changes to configure so it will work with dash
|
||||
when escape char processing bug is fixed (Ubuntu bug #268929)
|
||||
|
||||
2009-08-04 Release 1.3
|
||||
* Some API changes to comply with the current C++ standard
|
||||
binary_search algo returns true, not the found iterator
|
||||
stack and queue are now type templates, not container adaptors.
|
||||
Correctly set eof and fail flags in all stream functions
|
||||
This allows the use of the non-exception path in streams
|
||||
verify_remaining will no longer throw unless exceptions are on in the stream
|
||||
verify_remaining will return false if space is insufficient and set flags
|
||||
exceptions are on by default in istream and ostream and off elsewhere
|
||||
Updated return values of stream functions to match the standard
|
||||
what() on message exceptions returns the text passed to the ctor
|
||||
set insert also returns an iterator/bool pair
|
||||
map insert now returns an iterator,bool pair
|
||||
* streamsize and streamoff types defined
|
||||
* Added string resize with a value arg
|
||||
* Added standalone getline
|
||||
* Added numeric_limits digits and digits10
|
||||
* Name demangling is now an option, off by default, removing ~20k
|
||||
* A new and improved nonrecursive make system
|
||||
* Numerous small size and speed optimizations
|
||||
* A few minor bugfixes
|
||||
|
||||
2008-02-17 Release 1.2
|
||||
* Fixed ifstream readsome to work correctly on nonblocking fds.
|
||||
* Yet another try at fixing noalias rearrangments.
|
||||
Added a memory clobber and +g to noalias templates.
|
||||
* Added dtors template which will embody range destructors for
|
||||
destroy and vector dtor instead of vector deallocate. It is
|
||||
called by destroy through a selector template, turning it off
|
||||
completely for integral types. This removes empty deallocate
|
||||
instantiations for integral type vectors.
|
||||
* Fixed bitset stream_size (bits-words confusion)
|
||||
* Added workaround for compile error when printing a char array.
|
||||
* Added static_assert from Loki.
|
||||
|
||||
2007-09-02 Release 1.1
|
||||
* Due to the demise of SourceForge compile farm, this and subsequent
|
||||
releases are not as well tested the previous ones. So please
|
||||
report compilation problems, if any, on non-x86_64 platforms.
|
||||
* Fixed various aliasing problems complained about by gcc 4.2.
|
||||
* Added noalias_cast<type>(v) to aid in working around the above
|
||||
aliasing problem. The aliased variables also must be
|
||||
explicitly touched by an empty asm statement or something.
|
||||
* Reimplemented stream_size_of as a template stack because the old
|
||||
implmentation is invalid in gcc 4.2+ due to a change in
|
||||
overloaded set lookup scope. vector and tuple now have the
|
||||
standard read/write/stream_size members.
|
||||
* Reimplemented flow operators as templates.
|
||||
* STD_STREAMABLE and TEXT_STREAMABLE are no longer necessary.
|
||||
* Merged some template metaprogramming stuff from Alexandrescu's Loki
|
||||
library, including typelists and type traits.
|
||||
* Implemented generic macro list macros. See metamac.h.
|
||||
* Fixed some bsconf warnings.
|
||||
* memblock is_linked now correctly returns true when linked to NULL.
|
||||
* Added back() to string.
|
||||
* Fixed a memory leak in CBacktrace GetSymbols.
|
||||
* Changed written exception data to look like an IFF chunk.
|
||||
* Removed "memory" from some simd spec clobber lists.
|
||||
* Reduced the amount of code generated by vector stream templates.
|
||||
* talign will no longer generate a temp object when called with
|
||||
non-trivial classes. Uses NullValue template to avoid.
|
||||
* Linking with gcc instead of using -nodefaultlibs is simpler.
|
||||
* Removed link number overloads. Sadly, I don't know what this will
|
||||
break, if anything. On my machine the only case is link(p,0),
|
||||
which generates an ambiguity error and is easily fixed by
|
||||
explicitly casting the zero to a size_t. The benefit is
|
||||
cleaner code and fewer problems for the Symbian port, so the
|
||||
change stays until/unless somebody reports it as a problem.
|
||||
* Added long4grain and ptr4grain wrappers to explicitly write long
|
||||
values on 4-grain, even on 64bit platforms.
|
||||
|
||||
2006-10-27 Release 1.0 SVN 428
|
||||
* API CHANGE: ostringstream now works like std::ostringstream, with
|
||||
an internal buffer instead of writing to an external one
|
||||
through a link. Instead of passing the buffer to the ctor,
|
||||
write directly to a default-constructed stream object and
|
||||
assign buf = os.str() when finished.
|
||||
* Format change: containers will now write their size as a uint32_t
|
||||
instead of size_t to allow binary compatibility with 64 bit
|
||||
architectures. On 32 bit machines this makes no difference.
|
||||
* Renamed fdostringstream to ofstream.
|
||||
* Renamed fdistringstream to ifstream.
|
||||
* Renamed iterator_swap to iter_swap, as in the standard.
|
||||
* file.h/cc was removed; fstream replaces its functionality.
|
||||
* Added most remaining i/ostringstream functions that make sense in
|
||||
this implementation: str, put, get, getline, ignore, peek,
|
||||
readsome, putback, unget, tellg, seekg, sync, flush, seekp,
|
||||
tellp, good. The rest will probably not be implemented at
|
||||
all, since they reference streambufs which don't exist in uSTL.
|
||||
* Implemented fstream and used it in ifstream/ofstream.
|
||||
* Added remaining algorithms: find_end, find_first_of, includes,
|
||||
is_sorted, lexicographical_compare, max_element, min_element,
|
||||
partial_sort, partial_sort_copy, partition, next_permutation,
|
||||
prev_permutation, reverse_copy, rotate_copy, search, search_n,
|
||||
set_difference, set_intersection, set_symmetric_difference,
|
||||
set_union, and stable_partition. All the algorithms defined by
|
||||
the C++ standard are now implemented.
|
||||
* Made ios_base and ios classes instead of namespaces and derived
|
||||
all stream objects from ios_base. Pulled up state and all
|
||||
related functions into it. The only problem with this is that
|
||||
end() conflicts with seekdir end, so you'll need to use
|
||||
ios scope when you want the latter.
|
||||
* Align container ends on 4 grain.
|
||||
While this is not very friendly to 64bit architectures, it is
|
||||
the only way to allow writing containers portably. It is
|
||||
better to always align to an arbitrary value than to align to
|
||||
a platform-dependent one.
|
||||
* Removed non-const data pointer from memlink.
|
||||
While enforcing const-correctness is a good thing, the errors
|
||||
this catches are relatively rare and are all programmer errors.
|
||||
I must concede that the benefits of having memblocks, strings,
|
||||
and containers be 16 bytes in size is a great advantage in both
|
||||
speed and codesize. As a result, one needs to be more mindful
|
||||
to not modify memlink-derived objects that are linked to const
|
||||
data; before this change it would have caused a crash, now it
|
||||
might or might not do that, as with regular pointers.
|
||||
* Added CBacktrace class for printing backtrace information.
|
||||
* x86_64 cleanup and improvements, including MMX support.
|
||||
* Micro-optimization pass for size. Saved 24% (32k)!
|
||||
* exception now creates a backtrace when thrown.
|
||||
* Do cout.flush() before read in cin, like std does.
|
||||
* max_size() on linked objects should return size(), because it is.
|
||||
* >=, <=, and compare templates no longer require == (>= is !<)
|
||||
* Pulled rotate code into rotate_fast for memory blocks.
|
||||
* stream_bounds_exception demangles type names.
|
||||
* set,map,multiset,multimap now instantiate less crud.
|
||||
* Abandoned any attempt to use the goddamned byteswap.h.
|
||||
* Implemented bitset any, none, and count.
|
||||
* New popcount algorithms.
|
||||
* Implemented compose1 and compose2 extensions.
|
||||
* Support building as a .dylib on MacOS.
|
||||
* Removed --without-cout configure option.
|
||||
|
||||
2005-11-10 Release 0.8
|
||||
* API CHANGE: changed all string's find members to return offsets
|
||||
instead of iterators. That's what the STL standard requires.
|
||||
Also added standard-required replace/inserts with offset
|
||||
arguments. Yes, this is a bit painful. I was using it a lot...
|
||||
But it's all for the better. I promise!
|
||||
* Removed char_at and ichar from string; use utf8_begin/end instead.
|
||||
* Iterator-based string insert now return an iterator, like vector.
|
||||
* Added more wchar_t overloads to string, include append and assign.
|
||||
* Updated bsconf to use malloc instead of static buffers.
|
||||
* construct/destruct will now disappear for integral types.
|
||||
Integral types have no destructors/constructors.
|
||||
* Fixed istream_iterator to read on construction and in operator++
|
||||
as the standard says. Unfortunately, this makes it almost
|
||||
totally useless, since using it as a source for copy will
|
||||
always overread by one because copy will call ++ past the
|
||||
end, which will read one element past the end. This behaviour
|
||||
is understandable when reading to EOF (which is the only
|
||||
example ever shown for using it), but worthless when you
|
||||
have a fixed number of elements you want to read. I'm only
|
||||
using it to implement utf8 from streams, so, having fixed
|
||||
that to not overread, I'll chalk it up to standard
|
||||
compliance.
|
||||
* Made istream_iterator default constructible and implemented the
|
||||
EOF check during reading. This should make read-to-EOF
|
||||
scenario possible.
|
||||
* Made streams runtime bounds checking on by default.
|
||||
* Added operator-- to istream_iterator to do unputs.
|
||||
This works only once for variable-length types because there
|
||||
is no way to know the length to back up to get the element
|
||||
before the currently cached one. Constant-length types can
|
||||
be unput multiple times, and can use -= and - operators.
|
||||
* fdistringstream underflow will no longer erase the entire buffer.
|
||||
This helps to keep ungetc working most of the time.
|
||||
* Similarly fixed utf8in_iterator to read on construction.
|
||||
This fixed the double-advance bug in utf8in_iterator.
|
||||
* Fixed utf8in_iterator to not read ahead (except in constructor)
|
||||
before operator++ is called. This ensures that it does not
|
||||
read past the end of the string if it isn't 0-terminated.
|
||||
(Although it will still do so if you call ++)
|
||||
* Field width should be padded with spaces, not zeroes.
|
||||
* Implemented some heap algorithms.
|
||||
* Added VectorRange macro.
|
||||
* Added relink() call to memlinks for faster resizing.
|
||||
relink does the work of link, but without calling unlink.
|
||||
* Added to string substr and like functions.
|
||||
* Moved simd fill into ualgobase.cc
|
||||
* configure now recompiles bsconf if its sources change.
|
||||
* Fixed a rare off-by-one error in ostringstream vprintf.
|
||||
* Removed fdostringstream printf, since ostringstream has it already.
|
||||
* Fixed bsconf crash when all inline options are enabled.
|
||||
* Fixed crash when NULL filename given to file_exception.
|
||||
* Corrected potential buffer overflow in file_exception and sistream.
|
||||
* Fixed string rfind for strings; was returning a wrong value sometimes.
|
||||
* Added copy_link call to memblock to make a copy of linked data.
|
||||
* Added assert to memlink begin() to warn when writing to a const block.
|
||||
* Makefile now correctly uses ${MAKE} to recurse.
|
||||
* Removed all usage of "y" in SIMD asm blocks; gcc<4-> movd, not movq.
|
||||
This fixes problems with MMX fround on some platforms.
|
||||
* Removed SSE3 detection from bsconf; it just doesn't work!
|
||||
* Added BYTE_ORDER detection in bsconf.
|
||||
* Made BYTE_ORDER and bswap always defined.
|
||||
|
||||
2005-06-28 Release 0.7-1
|
||||
* Now compiles with gcc 4.0.0
|
||||
* Standard exception constructors now take const char* instead
|
||||
of string&; this generates much less code.
|
||||
* Fixed reversed conditional ostringstream.format
|
||||
This was causing a seek exception sometimes.
|
||||
* Added ostringstream.vformat
|
||||
* Added FPU registers to reset_mmx modlist; apparently gcc doesn't
|
||||
know that they are shared with MMX registers.
|
||||
* Moved simd copy into ualgobase.cc; they are not inlined anyway.
|
||||
* Added workaround for BSD which has no __va_copy.
|
||||
I wonder why nobody reported this as a bug. Is anyone running
|
||||
BSD out there? Anyone? Anyone at all? Is the damn thing dead?
|
||||
* So it now compiles on BSD again... Whoohoo...
|
||||
|
||||
2005-04-16 Release 0.7
|
||||
* Removed vector inheritance from memblock.
|
||||
There are just too many problems with treating a vector
|
||||
this way. You can still do it explicitly by linking a
|
||||
memblock to the vector. Removing the inheritance causes
|
||||
vector to be non-virtual, which drastically reduces
|
||||
instantiation cost.
|
||||
* Removed elementSize, elementBytes member functions from cmemlink.
|
||||
Only vector inheritance needed elementSize.
|
||||
* Restricted vector link calls to T* instead of void*.
|
||||
This way there would be explicit casts to warn of weirdness.
|
||||
* Optimized vector push_back
|
||||
* ostream will now zero bytes skipped by align.
|
||||
* memblock will no longer zero newly allocated storage.
|
||||
* Inlined empty constructors on map,multimap,set,multiset.
|
||||
* NUMERIC_LIMITS macros to facilitate specialization.
|
||||
* Fixed string vformat problem crashing on x86_64
|
||||
Because vsnprintf is called twice, need to copy arglist.
|
||||
* Added an rm before ln in install to avoid "already exists" errors.
|
||||
SunOS still doesn't know about the -f flag...
|
||||
* Split the distribution into ustl and ustl-docs
|
||||
* New SIZE_OF_BOOL system substitution in bsconf
|
||||
Only Alpha and Mac have bool as a long, so a define is better.
|
||||
* Fixed configure being confused with multiple gcc versions.
|
||||
* Reduced Align code for nonstandard values.
|
||||
* Pulled up vector/tuple stream operators into generic container
|
||||
templates in uctrstm.h and made use of resulting macros.
|
||||
* New TEMPLATE_TYPE macros to allow template building with macros.
|
||||
* Fixed SSE3 detection in bsconf; thanks to Aloysius Indrayanto.
|
||||
* Fixed get_temporary_buffer to return size in elements, not in bytes.
|
||||
This is the proper behaviour as specified in the C++ standard.
|
||||
* Now using libc qsort in the sort algorithm.
|
||||
This may give you trouble if you are using a custom comparator
|
||||
that requires initialization outside the constructor. You can
|
||||
write a wrapper class that does the initialization in the
|
||||
constructor. Or, you can use stable_sort.
|
||||
I'm doing this to both speed up the common case and to reuse
|
||||
the functionality already linked to in libc. If you really
|
||||
need to have a sort with a parametrized comparator and don't
|
||||
want to change your code, file a bug report and I'll change
|
||||
it back. I just don't think anyone is using this type of
|
||||
construction.
|
||||
* Finished heap algorithms.
|
||||
* Added priority_queue.
|
||||
* Added deque as a define to list.
|
||||
* Added noalias template to circumvent the type-punned pointer
|
||||
dereference warning given by gcc 4.1.0+
|
||||
|
||||
2005-01-17 Release 0.6
|
||||
* The library is relicensed under the MIT License (was LGPL)
|
||||
* Dropped support for locale due to its great complexity and ugliness.
|
||||
You can include <locale> from libstdc++ if you still want it.
|
||||
* ostringstream now uses snprintf for all integer types, so the output
|
||||
will be localized according to libc locale settings. As a side
|
||||
effect of this, you will not be able to print negative hex
|
||||
numbers any more (as in -6AD4), not that it was a good idea...
|
||||
* tuple will no longer align at the end:
|
||||
This affects you if you write tuples with small elements
|
||||
off default grain. For example, writing tuple<2,int16>
|
||||
on grain 2 would have aligned prior to this change, causing
|
||||
sub-optimal packing if you wrote an array of such tuples,
|
||||
since each one only needs grain 2 alignment.
|
||||
* Fixed incorrect use of __alignof__ in pair stream operators.
|
||||
* Added size_t ul-or-ui detection code to bsconf and fixed the
|
||||
size_t/pointer overload in uutility to use it.
|
||||
* Added erase(iterator,const_iterator) overload for string
|
||||
* Added alloca_link macro.
|
||||
* cmemlink will now throw bad_alloc if linking to !p && n.
|
||||
* multiset and multimap will insert equal elements in order.
|
||||
I wasn't able to find any guidance concerning the order of
|
||||
equal elements; it appears to be unspecified. Prior to this
|
||||
change equal elements were inserted in reverse order, which
|
||||
is bad idea because it causes a larger copy to make space.
|
||||
(Note that multimap only compares the key, since the mapped
|
||||
value is not required to have an operator<. If you want them
|
||||
sorted, you can use sort() on it.)
|
||||
* Fixed remove_copy algorithms to not require value operator !=.
|
||||
* bool will now be written as a byte regardless of the type size.
|
||||
* sistream now handles 64bit types correctly.
|
||||
|
||||
2004-11-11 Release 0.5
|
||||
* configure will now properly enable mmx compiler flags.
|
||||
* configure has a --with-profile option.
|
||||
* Fixed a bug in ostringstream format inserting extra '\0'
|
||||
* Fixed a bug in string find which sometimes did not match at the
|
||||
beginning of the text.
|
||||
* ostringstream will now use faster paged allocation.
|
||||
* New alignof specializations for cmemlink(size_t) and string(1)
|
||||
* Fixed tuple's value constructors to zero unspecified values.
|
||||
* Added parentheses around ctr argument in foreach for computed vars.
|
||||
* General simd interface for tuple optimization.
|
||||
* Proper link interface in vector, that takes element count.
|
||||
* set_terminate and set_unxpected prototypes are now available.
|
||||
* LOOKUP_TEXT_STREAMABLE macro for printing through name arrays.
|
||||
* Fixed iterator_swap to take iterators by value (reference& swap bad)
|
||||
* Container random_shuffle.
|
||||
* vformat method for string to allow implementation of custom printfs.
|
||||
* TestAndSet inline utility function with the cmpxchg instruction.
|
||||
* Fixed tuple stream_size_of to add up the elements if nonintegral.
|
||||
* Added is_integral member to numeric_limits for specialization aid.
|
||||
* Changed limits is_signed from a function to a bool like SGI does it.
|
||||
|
||||
2004-07-28 Release 0.4-3
|
||||
* A ChangeLog! After all these years...
|
||||
* SIMD instruction support for fill and copy
|
||||
* matrix template (on top of tuple)
|
||||
3dNow! instructions are supported for vector transforms.
|
||||
* New utility templates
|
||||
absv - absolute value.
|
||||
sign - -1 for negative, 0 for 0, 1 for positive
|
||||
abs_distance - returns an absolute value of the difference.
|
||||
distance - now returns ptrdiff_t, as in SGI STL.
|
||||
size_of_elements - useful for working with static arrays in
|
||||
templates; returns sizeof(T) * n.
|
||||
pack_type - useful for unrolling loops, packs a small
|
||||
type into a big one.
|
||||
alignof - recommended alignment for a type (uses GCC
|
||||
__alignof__ extension, if available)
|
||||
eachfor - same as foreach, but for reverse_iterator
|
||||
* get_temporary_buffer implemented using alloca and macros
|
||||
* Updated rotate to use alloca for small moves.
|
||||
This should speed up vector operations, like insert and erase.
|
||||
* Fixed copy_backward to actually copy backward rather than reverse.
|
||||
* Made resize virtual in memblock to properly handle strings.
|
||||
* sostream/sistream will handle wchar_t properly (as utf8 read/write)
|
||||
* ustring.cc: fixed multiple wchar_t insert
|
||||
* ustring.cc: changed allocation strategy to simply reserve the space
|
||||
for the null terminator instead of tweaking size() all the
|
||||
time. It's cleaner and saner this way.
|
||||
* benchmarking tool in bvt
|
||||
* More functions implemented in bitset.
|
||||
* Added --with-static and --without-shared flags to configure.
|
||||
|
||||
2004-05-22 Release 0.4-2
|
||||
* ostringstreams will now correctly resize the buffer as needed.
|
||||
* Fixed floating point output
|
||||
(well, not really, just switched to using snprintf)
|
||||
|
||||
750
extern/ustl/1.5/docs/index.html
vendored
Normal file
750
extern/ustl/1.5/docs/index.html
vendored
Normal file
@@ -0,0 +1,750 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>uSTL - the small STL library</title>
|
||||
<link rel="stylesheet" type="text/css" href="style/default.css" />
|
||||
<meta http-equiv="Content-Type" content="text/xhtml+xml; charset=ISO-8859-1" />
|
||||
<meta name="Description" content="API and usage description for uSTL, a size-optimized STL implementation" />
|
||||
<meta name="Keywords" content="C++, STL, template, bloat, optimization" />
|
||||
<meta name="author" content="Mike Sharov" />
|
||||
<meta name="date" content="2011-03-16" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="banner">
|
||||
<h1>uSTL</h1>
|
||||
<div class="motto">Candy for the optimization nut in you</div>
|
||||
</div>
|
||||
<hr class="banner" />
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>
|
||||
The C++ standard template library (STL) is a collection of common
|
||||
containers and algorithms in template form. Unfortunately its standard
|
||||
incarnation shipped with gcc is implemented without much concern for code
|
||||
size. Not only is the library itself large, the current version being
|
||||
over a megabyte in size, but with all the code you instantiate by using a
|
||||
vector for each of your containers, it is easy to become fearful and opt
|
||||
for using static arrays instead or, worse yet, abandon C++ altogether
|
||||
for C. This is especially painful to former DOS assembly programmers
|
||||
like myself, who fret endlessly when the size of the executable crosses
|
||||
the magic 64k boundary, forgetting that nobody cares about memory anymore.
|
||||
</p><p>
|
||||
Of course, these days everyone has gigabytes of RAM and has no compunction
|
||||
about loading up OpenOffice, whose source tree is over a gigabyte in
|
||||
size. Why then bother with saving a kilobyte of code here and there? I
|
||||
can't really say. Maybe it's that warm fuzzy knowledge that you are making
|
||||
maximum possible use of your computer's resources. Maybe it's that thrill
|
||||
you get after expressing your program's functionality in the fewest
|
||||
possible instructions and the minimum imaginable overhead. Or maybe it
|
||||
really is of no importance and any code bloat will be easily overcome
|
||||
by faster processors in some near future. I just know what I like, and
|
||||
it's the sight of clean, concise, and fast code. Therefore this library.
|
||||
</p>
|
||||
<h2>Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#Installation">Installation</a></li>
|
||||
<li><a href="#Containers">Containers and Iterators</a></li>
|
||||
<li><a href="#Strings">Strings</a></li>
|
||||
<li><a href="#Algorithms">Algorithms</a></li>
|
||||
<li><a href="#Memblocks">Memblock and Memlink</a></li>
|
||||
<li><a href="#Streams">Streams</a></li>
|
||||
<li><a href="#Tuples">Tuples</a></li>
|
||||
<li><a href="#Exceptions">Exceptions</a></li>
|
||||
<li><a href="#Savings">Template Bloat Be Gone</a></li>
|
||||
<li><a href="#Contact">Bug reporting</a></li>
|
||||
<li><a href="html/index.html">Doxygen reference</a></li>
|
||||
</ul>
|
||||
<h2><a name="Installation">Installation</a></h2>
|
||||
<p>
|
||||
To start with you'll need a decent compiler. Although uSTL will compile
|
||||
under gcc 2.95, some features require at least gcc 3.4 and are simply
|
||||
turned off with an older version. C++ support is vastly improved in
|
||||
the recent compiler versions, and I strongly recommend gcc 4 for best
|
||||
possible code.
|
||||
</p><p>
|
||||
The latest version of uSTL can always be downloaded from its SourceForge
|
||||
<a href="https://sourceforge.net/project/showfiles.php?group_id=76798">project files page</a>.
|
||||
If you like living dangerously, you can pull the working branch directly from
|
||||
<a href="http://ustl.git.sourceforge.net/git/gitweb.cgi?p=ustl">git://ustl.git.sourceforge.net/gitroot/ustl/ustl</a>.
|
||||
The mainline source should build on any unix-based system, including Linux,
|
||||
BSD, MacOS, SunOS, and Solaris. A separate port for Symbian OS is maintained by
|
||||
<a href="http://www.penrillian.com/index.php?option=com_content&task=view&id=82&Itemid=73">Penrillian</a>.
|
||||
Windows-based systems and weird embedded platforms, are not, and will
|
||||
not be supported by the mainline. However, if you make a port, I'll be
|
||||
happy to mention it here. After unpacking:
|
||||
</p><pre>
|
||||
./configure
|
||||
make install
|
||||
</pre><p>
|
||||
<kbd>./configure --help</kbd> lists available build options.
|
||||
You might want to specify a different installation prefix with
|
||||
<kbd>--prefix=/usr</kbd>; the default destination is /usr/local.
|
||||
Developers will want to build with <kbd>--with-debug</kbd> to get a
|
||||
lot of assert error checking, which I highly recommend. If you have
|
||||
gcc 4.4 or later, you may want to also use <kbd>--force-inline</kbd>
|
||||
(see the bottom of this page for a fuller explanation). If you are the
|
||||
type to edit configuration manually, it's in Config.mk and config.h. When
|
||||
it's built, you can run the included tests with <kbd>make check</kbd>.
|
||||
Finally, here's a simple hello world application:
|
||||
</p><pre>
|
||||
#include <ustl.h>
|
||||
using namespace ustl;
|
||||
|
||||
int main (void)
|
||||
{
|
||||
cout << "Hello world!\n";
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
</pre><p>
|
||||
If you have at least gcc 3.4, uSTL is built as a standalone library,
|
||||
without linking to libstdc++ (except on BSD platforms where gcc does not
|
||||
support it) Because g++ links to it by default, you'll need to link your
|
||||
applications with gcc, or to pass <kbd>-nodefaultlibs -lc</kbd> to g++
|
||||
if you want to use uSTL to completely replace libstdc++. This is where
|
||||
the actual space savings happen. (If you want to see just how much you can
|
||||
save, skip to the <a href="#Savings">Template Bloat Be Gone</a> section)
|
||||
</p>
|
||||
<h2><a name="Containers">Containers and Iterators</a></h2>
|
||||
<p>
|
||||
STL containers provide a generic abstraction to arrays, linked lists,
|
||||
and other methods of memory allocation. They offer the advantages
|
||||
of type-safety, the peace of mind that comes from never having to
|
||||
malloc anything again, and a standard access API called iterators. Each
|
||||
container's API is equivalent to that of a simple array, with iterators
|
||||
being the equivalent of pointers into the array. The uniform access
|
||||
API allows creation of standardized algorithms, discussed futher down,
|
||||
that work on any container. Here are some examples of using vector,
|
||||
the container representing a simple array:
|
||||
</p><pre>
|
||||
vector<int> v;
|
||||
v.push_back (1);
|
||||
v.push_back (2);
|
||||
v[1] = 0;
|
||||
v.erase (v.begin() + 1);
|
||||
v.pop_back();
|
||||
v.insert (v.begin(), 4);
|
||||
v.resize (15);
|
||||
</pre><p>
|
||||
As you can see, a vector is basically the same thing as the arrays
|
||||
you use now, except that it is resizable. The function names
|
||||
ought to be self-explanatory with the exception of the addressing
|
||||
arguments. You can do index addressing and get free bounds checking
|
||||
with asserts. Incidentally, I highly recommend you work with a debug
|
||||
build when writing code; uSTL is chock full of various asserts checking
|
||||
for error conditions. In the optimized build, most such errors will be
|
||||
silently ignored where possible and will cause crashes where not. That
|
||||
is so because they are programmer errors, existing because you have a
|
||||
bug in your code, not because the user did something wrong, or because
|
||||
of some system failure. Programmer errors assert. User or system errors
|
||||
throw exceptions.
|
||||
</p><p>
|
||||
Vectors are addressed with iterators, which are just like pointers (and
|
||||
usually are). Calling begin() gives you the pointer to the first element,
|
||||
calling end() gives you the pointer to the end of the last element. No,
|
||||
not the last element, the end of it, or, more accurately, the end of the
|
||||
array. It's that way so you can keep incrementing an iterator until it
|
||||
is equal to the end() value, at which point you know you have processed
|
||||
all the elements in the list. This brings me to demonstrate how you
|
||||
ought to do that:
|
||||
</p><pre>
|
||||
foreach (vector<int>::iterator, i, v)
|
||||
if (*i < 5 || *i > 10)
|
||||
*i = 99;
|
||||
</pre><p>
|
||||
Although the foreach macro is a uSTL-only extension, it is a one-liner
|
||||
you can easily copy out of uutility.h if you ever want to switch back to
|
||||
regular STL. It is a great way to ensure you don't forget to increment
|
||||
the counter or run past the end of the vector. The only catch to be aware
|
||||
of, when inside an iterator loop, is that if you modify the container,
|
||||
by adding or removing entries, you have to update the iterator, since the
|
||||
container memory storage may have moved when resized. So, for example,
|
||||
if you wish to remove certain types of elements, you'd need to do use
|
||||
an index loop or something like:
|
||||
</p><pre>
|
||||
foreach (vector<CEmployee>::iterator, i, employees)
|
||||
if (i->m_Salary > 50000 || i->m_Performance < 100)
|
||||
--(i = employees.erase (i));
|
||||
</pre><p>
|
||||
This is pretty much all there is to say about containers. Create them,
|
||||
use them, resize them, that's what they are for. There are other
|
||||
container types, but you will probably not use them much. There's
|
||||
<code>set</code>, which is a perpetually sorted vector, useful when you
|
||||
want to binary_search a large collection. There's <code>map</code> which
|
||||
is an associative container where you can look up entries by key. Its
|
||||
utility goes down drastically when you have complex objects that need to
|
||||
be searched with more than one parameter, in which cast you are better
|
||||
off with vector and foreach. I have never needed the others, and do
|
||||
not recommend their use. Their implementations are fully functional,
|
||||
but do not conform to STL complexity guarantees and are implemented as
|
||||
aliases to vector, which naturally changes their performance parameters.
|
||||
</p>
|
||||
<h2><a name="Strings">Strings</a></h2>
|
||||
<p>
|
||||
Every program uses strings, and STL was kind enough to provide a
|
||||
specification. uSTL deviates a bit from the standard by not implementing
|
||||
wchar strings. There is only one <code>string</code> class, which assumes
|
||||
all your strings will be UTF8-encoded, and provides some additional
|
||||
functionality to make working with those easier. I did that for the same
|
||||
reason I dropped the locale classes; bloat. It is simply too expensive to
|
||||
implement the standard locale classes, as the enormous size of libstdc++
|
||||
illustrates. If you need them, you can still include them from libstdc++,
|
||||
but it may be just as simple to use the locale support provided by libc
|
||||
through printf, which may be called through <code>format</code> functions
|
||||
in string and ostringstream.
|
||||
</p><p>
|
||||
Anyway, back to strings. You can think of the string object as a
|
||||
char vector with some additional operations built-in, like searching,
|
||||
concatenation, etc.
|
||||
</p><pre>
|
||||
string s ("Hello");
|
||||
s += ' ';
|
||||
s += "world?";
|
||||
s.replace (s.find ('?'), 1, "!");
|
||||
s[3] = s[s.find_first_of("lxy")];
|
||||
s[s.rfind('w')] = 'W';
|
||||
s.format ("A long %zd number of 0x%08lX\n", 345u, 0x12345);
|
||||
cout << s << endl;
|
||||
</pre><p>
|
||||
A nonstandard behaviour you may encounter is from linked strings created
|
||||
by the string constructor when given a null-terminated const string. In
|
||||
the above example, the constructor links when given a const string and
|
||||
stays as a const link until the space is added. If you try to write to it,
|
||||
you'll get an assert telling you to use copy_link first to convert the
|
||||
link into a copy. Resizing the linked object automatically does that for
|
||||
you, so most of the time it is transparent. You may also encounter another
|
||||
instance of this if you try getting iterators from such an object. The
|
||||
compiler uses the non-const accessors by default for local objects,
|
||||
so you may need to declare it as a const string if you don't wish to
|
||||
copy_link. Why does uSTL string link instead of copying? To save space
|
||||
and time. All those strings are already in memory, so why waste heap
|
||||
space and processor time to copy them if you just want to read them? I
|
||||
thought it a good tradeoff, considering that it is trasparent for the
|
||||
most common uses.
|
||||
</p><p>
|
||||
Other nonstandard extensions include a <code>format</code> function to
|
||||
give you the functionality of sprintf for string objects. Another is
|
||||
the UTF8 stuff. Differing a bit from the standard, <code>size</code>
|
||||
returns the string length in bytes, <code>length</code> in characters.
|
||||
You can iterate by characters instead of bytes with a special utf8
|
||||
iterator:
|
||||
</p><pre>
|
||||
for (string::utf8_iterator i = s.utf8_begin(); i < s.utf8_end(); ++ i)
|
||||
DrawChar (*i);
|
||||
</pre><p>
|
||||
or just copy all the chars into an array and iterate over that:
|
||||
</p><pre>
|
||||
vector<wchar_t> result (s.length());
|
||||
copy (s.utf8_begin(), s.utf8_end(), result.begin());
|
||||
</pre><p>
|
||||
To write wide characters to the string, wchar_t values can be directly
|
||||
given to push_back, insert, append, or assign, in the same way as the
|
||||
char ones.
|
||||
</p><p>
|
||||
A few words must be said regarding reading wide characters. The shortest
|
||||
possible rule to follow is "don't!" I have received a few complaints about
|
||||
the fact that all offsets given to and returned by string functions are
|
||||
byte offsets and not character offsets. The problem with modifying or even
|
||||
looking for specific wide characters is that you are not supposed to know
|
||||
what they are. Your strings will be localized into many languages and it
|
||||
is impossible for you to know how the translation will be accomplished.
|
||||
As a result, whenever you are hardcoding a specific character value,
|
||||
or a specific character length (like a three-character extension),
|
||||
you are effectively hardcoding yourself into a locale. The only valid
|
||||
operation on localized strings is parsing it via standard delimiters,
|
||||
treating anything between those delimiters as opaque blocks. For this
|
||||
reason, whenever you think you need to do something at a particular
|
||||
character offset, you should recognize it as a mistake and find the
|
||||
offset by the content that is supposed to be there.
|
||||
</p><p>
|
||||
If this philosophy is consistently followed, it becomes clear that
|
||||
actual character boundaries are entirely irrelevant. There are only
|
||||
two exceptions to this: first occurs if you are writing a text editor
|
||||
and want to insert user data at a character position, the second occurs
|
||||
if you are writing a font renderer and want to translate characters to
|
||||
glyphs. In both cases you should make use of the utf8_iterator to find
|
||||
character boundaries and values. Given that these two cases apply to
|
||||
just a handful of people who are involved in implementing user interface
|
||||
frameworks, I believe that the opacity restriction is well justified by
|
||||
the amount of code space it saves for the vast majority of library users.
|
||||
</p>
|
||||
<h2><a name="Algorithms">Algorithms</a></h2>
|
||||
<p>
|
||||
Algorithms are the other half of STL. They are simply templated common
|
||||
tasks that take iterator arguments, and as a result, work with any
|
||||
container. Most will take an iterator range, like (v.begin(), v.end()),
|
||||
but you can, of course operate on a subset of a container by giving a
|
||||
different one. Because the usual operation is to use the whole container,
|
||||
uSTL provides versions of most algorithms that take container arguments
|
||||
instead of the iterator range. Here are the algorithms you will actually
|
||||
find useful:
|
||||
</p><pre>
|
||||
copy (v1, v2.begin()); // Copies vector v1 to vector v2.
|
||||
fill (v, 5); // Fills v with fives.
|
||||
copy_n (v1, 5, v2.begin()); // Copies first five elements only.
|
||||
fill_n (v.begin() + 5, 10, 5); // Fills elements 5-15 with fives.
|
||||
sort (v); // Sorts v.
|
||||
find (v, 14); // Finds 14 in v, returning its iterator.
|
||||
binary_search (v, 13); // Looks up 13 with binary search in a sorted vector.
|
||||
lower_bound (v, 13); // Returns the iterator to where you want to insert 13.
|
||||
iota (v.begin(), v.end(), 0); // Puts 0,1,2,3,4,... into v.
|
||||
reverse (v); // Reverses all the elements in v.
|
||||
</pre><p>
|
||||
The rest you can discover for yourself. There are obscure mathematical
|
||||
operations, like inner_product, set operations, heap operations, and
|
||||
lots and lots of predicate algorithms. The latter are algorithms that
|
||||
take a functor (an object that can be called like a function) and were
|
||||
supposed to help promote code reuse by encapsulating common operations.
|
||||
For example, STL expects you to use the <code>for_each</code> algorithm and
|
||||
write a little functor for all your iterative tasks:
|
||||
</p><pre>
|
||||
class CCompareAndReplace {
|
||||
public:
|
||||
CCompareAndReplace (int minValue, int maxValue, int badValue)
|
||||
: m_MinValue (minValue), m_MaxValue (maxValue), m_BadValue (badValue) {}
|
||||
void operator (int& v) {
|
||||
if (v < m_MinValue || v > m_MaxValue)
|
||||
v = m_BadValue;
|
||||
}
|
||||
private:
|
||||
int m_MinValue;
|
||||
int m_MaxValue;
|
||||
int m_BadValue;
|
||||
};
|
||||
|
||||
for_each (v.begin(), v.end(), CCompareAndReplace (5, 10, 99));
|
||||
</pre><p>
|
||||
And yes, it really does work. Doesn't always generate much bloat either,
|
||||
since the compiler can often see right through all this trickery and
|
||||
expand the for_each into a loop without actually creating the functor
|
||||
object. However, the compiler has a much harder time when you start
|
||||
using containers of complex objects or operating on member variables
|
||||
and member functions. Since that is what you will most likely have in
|
||||
any real code outside the academic world, the utility of predicate
|
||||
algorithms is questionable. Their readability is even more so,
|
||||
considering that the above fifteen line example can be written as a
|
||||
three line iterative foreach loop. Finally, there is the problem of
|
||||
where to put the functor. It just doesn't seem to "belong" anywhere in
|
||||
the object-oriented world. (C++0x changes that somewhat with lambda
|
||||
functions) Sorry, Stepanov, I just don't see how these things can be
|
||||
anything but an ugly, bloated hindrance.
|
||||
</p>
|
||||
<h2><a name="Memblocks">Memblocks and Memlinks</a></h2>
|
||||
<p>
|
||||
The STL specification is only about containers and algorithms, the stuff
|
||||
described from here on is totally non-standard, so by using them you'll
|
||||
have to stick with uSTL as your STL implementation. I think it's worth
|
||||
it, but, of course, the choice is up to you.
|
||||
</p><p>
|
||||
The major difference between the standart STL implementation and uSTL is
|
||||
that the former has memory management stuff all over the place, while
|
||||
the latter keeps it all together in the <code>memblock</code> class. Normally
|
||||
STL containers are resized by calling <code>new</code> to create more storage
|
||||
and then copying the elements there from the old one. This method wastes
|
||||
space by fragmenting memory, wastes time by copying all the existing data
|
||||
to the new location, and wastes codespace by having to instantiate all
|
||||
the resizing code for each and every container type you have. This method
|
||||
is also absolutely necessary to do this resizing in a perfectly object-safe
|
||||
way. The uSTL way is to manage memory as an opaque, typeless block, and
|
||||
then use the container templates to cast it to an appropriate pointer type.
|
||||
</p><p>
|
||||
This works just fine, except for one little catch: there is one type
|
||||
of object you can't store in uSTL containers -- the kind that has pointers
|
||||
to itself. In other implementations, resizing actually creates new objects
|
||||
in the new location and destroys them in the old location. uSTL simply
|
||||
memcpys them there without calling the copy constructor. In other words,
|
||||
the object can not rely on staying at the same address. Most objects really
|
||||
don't care. Note that this is not the same thing as doing a bitwise copy,
|
||||
that you were rightly warned against before! It's a bitwise <em>move</em>
|
||||
that doesn't create a new object, but simply relocates an existing one.
|
||||
</p><p>
|
||||
What this one small concession does is allow aggregation of all memory
|
||||
management in one place, namely, the <code>memblock</code> class. All the
|
||||
containers are thus converted mostly into typecasting wrappers that
|
||||
exist to ensure type safety. Look at the assembly code and you'll see
|
||||
mostly calls to memblock's functions. This is precisely the feature
|
||||
that allows reduction in code instantiated by container templates.
|
||||
</p><p>
|
||||
However, memblock's usefulness doesn't end there! It can now replace
|
||||
all your dynamically allocated buffers that you use for unstructured
|
||||
data. Need to read a file? Don't use new to allocate memory; use a
|
||||
memblock! It even has a friendly read_file member function for just
|
||||
that purpose. Need to write a file? Use the write_file call! Unless
|
||||
you are working with a database or some really large archive, you
|
||||
should be able to load all your files this way. Imagine, not having
|
||||
to worry about file I/O again! It's much nicer to work with data in
|
||||
memory; you know how long it is, so you know when to stop. You can
|
||||
seek with impunity, and any operations have the cost of a memcpy.
|
||||
</p><p>
|
||||
Memblock is derived from memlink, an object for linking to a memory
|
||||
block. Now you get to store a pointer and the size of whatever it
|
||||
points to, but with uSTL you can use a memlink object to keep them
|
||||
together, reducing source clutter and making your code easier to
|
||||
read and maintain. You can link to constant blocks too with cmemlink,
|
||||
from which memlink is derived. Because all three are in a single
|
||||
hierarchy, you never need to care whether you're working on an
|
||||
allocated block or on somebody else's allocated block. Pointers are
|
||||
kept together with block sizes, memory is freed when necessary,
|
||||
and you never have to call new or delete again. Who needs garbage
|
||||
collection? Memblocks give you the same functionality at a fraction
|
||||
of the cost.
|
||||
</p><p>
|
||||
Linking is not limited to memlink. You can link memblock objects.
|
||||
You can link string objects. You can even link containers! Now
|
||||
you can use alloca to create a vector on the stack; use the
|
||||
<code>typed_alloca_link(v,int,99)</code> macro. All linked objects
|
||||
will allocate memory and copy the linked data when you increase their
|
||||
size. You can also do it explicitly by calling <code>copy_link</code>.
|
||||
Why link? It's cheaper than copying and easier than keeping track
|
||||
of pointers. For example, here's a line parser:
|
||||
</p><pre>
|
||||
string buf, line;
|
||||
buf.read_file ("some_config_file.txt");
|
||||
for (uoff_t i = 0; i < buf.size(); i += line.size() + 1) {
|
||||
line.link (buf.iat(i), buf.iat (buf.find ('\n',i)));
|
||||
process_line (line);
|
||||
}
|
||||
</pre><p>
|
||||
This way process_line gets a string object instead of a pointer and
|
||||
a size. If you don't rely on the string being null-terminated, which
|
||||
basically means not using libc functions on it, this is all you need.
|
||||
Otherwise buf will have to be writable and you can replace the newline
|
||||
with a null. In either case you are using no extra heap. The overhead
|
||||
of link is negligible in most cases, but if you really want to do this
|
||||
in a tight loop, you can use relink call, which expands completely
|
||||
inline into one or two instructions, avoiding the virtual unlink() call.
|
||||
</p>
|
||||
<h2><a name="Streams">Streams</a></h2>
|
||||
<p>
|
||||
The C++ standard library provides global stream objects called cin,
|
||||
cout, and cerr to replace printf and friends for accessing stdin, stdout,
|
||||
and stderr, respectively. uSTL versions work mostly the same as the
|
||||
standard ones (yes, the <code>format</code> call is a uSTL extension). Most
|
||||
calls use snprintf for output and thus use whatever locale libc uses.
|
||||
</p><pre>
|
||||
cout << "Hello world!" << endl;
|
||||
cout << 456 << ios::hex << 0x1234 << endl;
|
||||
cerr.format ("You objects are at 0x%08X\n", &o);
|
||||
</pre><p>
|
||||
String-writing streams are also available:
|
||||
</p><pre>
|
||||
ostringstream os;
|
||||
os << "Writing " << n << " objects somewhere" << endl;
|
||||
cout << os.str() << endl;
|
||||
</pre><p>
|
||||
fstream is a file access interface with exception handling for errors:
|
||||
</p><pre>
|
||||
fstream f;
|
||||
// C++ standard says that fstream does not throw by default,
|
||||
f.exceptions (fstream::allbadbits); // so this enables throwing.
|
||||
f.open ("file.dat", ios::in | ios::out); // throws file_exception
|
||||
f.read (buf, bufSize); // let's read something
|
||||
f.seek (334455); // go somewhere
|
||||
f.write (buf2, buf2Size); // and write something
|
||||
f.fnctl (FCNTLID(F_SETFL), O_NONBLOCK); // yup, ALL file operations
|
||||
memlink l = f.mmap (bufSize, offset); // even mmap
|
||||
fill (l, 0);
|
||||
f.msync (l);
|
||||
f.munmap (l);
|
||||
f.close(); // also throws file_exception (with filename!)
|
||||
</pre><p>
|
||||
istream and ostream, which are not really usable by themselves in the
|
||||
standard implementation, are hijacked by uSTL to implement binary data
|
||||
input and output:
|
||||
</p><pre>
|
||||
const size_t writtenSize =
|
||||
Align (stream_size_of(number) +
|
||||
stream_size_of(ctr)) +
|
||||
stream_size_of(n) +
|
||||
stream_size_of(v);
|
||||
memblock buf (writtenSize);
|
||||
ostream os (buf);
|
||||
os << number << ctr;
|
||||
os.align();
|
||||
os << n << v;
|
||||
</pre><p>
|
||||
These operations are all very efficient, approaching a straight memcpy
|
||||
in performance. ostream will not resize the buffer, hence the necessity
|
||||
to estimate the final size. Most stream_size_of calls are computed at
|
||||
compile time and thus produce no code. Because the data is written as
|
||||
is, it is necessary to consider proper data alignment; for example,
|
||||
a 4 byte int can not be written at stream offset 2. Some architectures
|
||||
(Macs) actually crash when doing it; Intel processors just do it slowly.
|
||||
Hence the need to pack the data to a proper "grain". The default align
|
||||
call will pack to the maximum necessary grain, but can be given an
|
||||
argument to change that. In case you're wondering, the reason for all
|
||||
these idiosyncracies is optimization. The smallest and fastest possible
|
||||
code to dump your stuff into a binary file is produced by this method.
|
||||
uSTL defines flow operators to write integral values, strings, and
|
||||
containers, but you can custom-serialize your objects like this:
|
||||
</p><pre>
|
||||
namespace myns {
|
||||
|
||||
/// Some class I want to serialize
|
||||
class CMyClass {
|
||||
public:
|
||||
void read (istream& is);
|
||||
void write (ostream& os) const;
|
||||
size_t stream_size (void) const;
|
||||
private:
|
||||
vector<int> m_Elements; ///< A bunch of elements.
|
||||
size_t m_SomeSize; ///< Some integral value.
|
||||
MyObject m_SomeObject; ///< Some other streamable object.
|
||||
}
|
||||
|
||||
/// Reads the object from stream \p is.
|
||||
void CMyClass::read (istream& is)
|
||||
{
|
||||
is >> m_Elements >> m_SomeSize >> m_SomeObject;
|
||||
}
|
||||
|
||||
/// Writes the object to stream \p os.
|
||||
void CMyClass::write (ostream& os) const
|
||||
{
|
||||
os << m_Elements << m_SomeSize << m_SomeObject;
|
||||
}
|
||||
|
||||
/// Returns the size of the written object.
|
||||
size_t CMyClass::stream_size (void) const
|
||||
{
|
||||
return (stream_size_of (m_Elements) +
|
||||
stream_size_of (m_SomeSize) +
|
||||
stream_size_of (m_SomeObject));
|
||||
}
|
||||
|
||||
} // namespace myns
|
||||
</pre>
|
||||
<h2><a name="Tuples">Tuples</a></h2>
|
||||
<p>
|
||||
One last container I'll mention is a <code>tuple</code>, which is a
|
||||
fixed-size array of identical elements. No, it's not the same as the tuple
|
||||
in boost, which is more like a template-defined struct. This one should
|
||||
have been named "array", which is what it will be called in the next STL
|
||||
standard, but I guess I'm stuck with the name now. What are they good
|
||||
for? Graphical objects. Points, sizes, rectangles, triangles, etc. As a
|
||||
bonus, operations on tuples can automatically use SIMD instructions if
|
||||
they are available. Any fixed size-array also works better as a tuple,
|
||||
since it becomes a standard STL container, which you can use with any
|
||||
algorithm, copy by assignment, initialize in the constructor, etc.
|
||||
</p><pre>
|
||||
typedef int32_t coord_t;
|
||||
typedef tuple<2, coord_t> Point2d;
|
||||
typedef tuple<2, coord_t> Size2d;
|
||||
typedef tuple<2, Point2d> Rect;
|
||||
|
||||
Rect r (Point2d (1,2), Point2d (3,4));
|
||||
r += Size2d (4, 4);
|
||||
r[1] -= Size2d (1, 1);
|
||||
foreach (Rect::iterator, i, r)
|
||||
TransformPoint (*i);
|
||||
Point2d pt (1, 2);
|
||||
pt += r[0];
|
||||
pt *= 2;
|
||||
</pre>
|
||||
<h2><a name="Exceptions">Exceptions</a></h2>
|
||||
<p>
|
||||
uSTL implements all the standard exception classes defined by the
|
||||
C++ standard. The exception tree is standalone, but is derived
|
||||
from std::exception when compiling with libstdc++ for ease of
|
||||
catching everything. uSTL exceptions implement some additional useful
|
||||
features. First, they are completely serializable. You can write them
|
||||
as a binary blob into a file, send them over a network, and handle them
|
||||
somewhere else. Each exception will print an informative error message
|
||||
directly to a text stream, reducing your try/catch block to:
|
||||
</p><pre>
|
||||
try {
|
||||
DoSomething();
|
||||
} catch (exception& e) {
|
||||
cerr << "Error: " << e << endl;
|
||||
#ifndef NDEBUG
|
||||
cerr << e.backtrace();
|
||||
#endif
|
||||
} catch (...) {
|
||||
cerr << "Unexpected fatal error has occured.\n";
|
||||
}
|
||||
</pre><p>
|
||||
Second, each exception stores a backtrace (callstack) at the time
|
||||
of throwing and can print that backtrace as easily as the above
|
||||
example illustrates. While it is indeed a good practice to design
|
||||
your exceptions so that you should not care where it was thrown from,
|
||||
situations occasionally arise while debugging where knowing the thrower
|
||||
is useful to fix the bug a little faster than otherwise.
|
||||
</p><p>
|
||||
Finally, there are additional exception classes for dealing with libc
|
||||
function errors, file errors, and stream classes. libc_exception can
|
||||
be thrown whenever a libc function fails, immediately telling you
|
||||
what the function call was and the errno description of the failure.
|
||||
file_exception, thrown by fstream operations, also contains the file name,
|
||||
which can be pretty darn useful. stream_bounds_exception is extremely
|
||||
useful in debugging corrupted data, as it tells you exactly where the
|
||||
corruption starts and what you were trying to read there.
|
||||
</p>
|
||||
<h2><a name="Savings">Template Bloat Be Gone</a></h2>
|
||||
<p>
|
||||
So how much space are you going to save and where? Allow me to demonstrate with
|
||||
the following small program. I'm basically creating a vector and exercise the
|
||||
most common operations. Those are resize, push_back, insert, and erase, which
|
||||
you use pretty much every time you have a vector.
|
||||
</p><pre>
|
||||
#if USING_USTL
|
||||
#include <ustl.h>
|
||||
using namespace ustl;
|
||||
#else
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
int main (void)
|
||||
{
|
||||
vector<int> v;
|
||||
v.resize (30);
|
||||
for (size_t i = 0; i < v.size(); ++ i)
|
||||
v[i] = i;
|
||||
v.push_back (57);
|
||||
v.insert (v.begin() + 20, 555);
|
||||
v.erase (v.begin() + 3);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
</pre><p>
|
||||
Feel free to compile it and see for yourself. I'm compiling on a Core
|
||||
i7 with gcc 4.5.2 and <kbd>-Os -DNDEBUG=1</kbd>. The libstdc++ version
|
||||
is linked implicitly with it, and uSTL version is linked with gcc
|
||||
(instead of g++) and <kbd>-lustl</kbd>. Both executables are stripped.
|
||||
The libstdc++ version looks like this:
|
||||
</p><pre>
|
||||
% ls -l std/tes
|
||||
7096 tes
|
||||
% size std/tes
|
||||
text data bss dec hex filename
|
||||
3780 632 16 4428 114c std/tes
|
||||
% size -A std/tes.o
|
||||
std/tes.o :
|
||||
section size
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.group 8
|
||||
.text 256
|
||||
.data 0
|
||||
.bss 0
|
||||
.text._ZNSt6vectorIiSaIiEED2Ev 8
|
||||
.text._ZNKSt6vectorIiSaIiEE12_M_check_lenEmPKc 68
|
||||
.text._ZNSt11__copy_moveILb0ELb1ESt26random_access_iterator_tagE8__copy_mIiEEPT_PKS3_S6_S4_ 51
|
||||
.text._ZSt14__copy_move_a2ILb0EN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEES6_ET1_T0_S8_S7_ 14
|
||||
.text._ZSt4copyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEES6_ET0_T_S8_S7_ 14
|
||||
.text._ZNSt20__copy_move_backwardILb0ELb1ESt26random_access_iterator_tagE13__copy_move_bIiEEPT_PKS3_S6_S4_ 63
|
||||
.rodata.str1.1 45
|
||||
.text._ZNSt6vectorIiSaIiEE14_M_fill_insertEN9__gnu_cxx17__normal_iteratorIPiS1_EEmRKi 355
|
||||
.text._ZNSt6vectorIiSaIiEE6resizeEmi 64
|
||||
.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi 195
|
||||
.text._ZNSt6vectorIiSaIiEE9push_backERKi 46
|
||||
.text._ZNSt6vectorIiSaIiEE6insertEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi 79
|
||||
.gcc_except_table 14
|
||||
.comment 40
|
||||
.note.GNU-stack 0
|
||||
.eh_frame 576
|
||||
Total 1976
|
||||
</pre><p>
|
||||
The uSTL version looks like this:
|
||||
</p><pre>
|
||||
% ls -l ustl/tes
|
||||
5720 tes
|
||||
% size ustl/tes
|
||||
text data bss dec hex filename
|
||||
2435 616 16 3067 bfb ustl/tes
|
||||
% size -A ustl/tes.o
|
||||
ustl/tes.o :
|
||||
section size addr
|
||||
.text 327 0
|
||||
.data 0 0
|
||||
.bss 0 0
|
||||
.gcc_except_table 19 0
|
||||
.comment 40 0
|
||||
.note.GNU-stack 0 0
|
||||
.eh_frame 88 0
|
||||
Total 474
|
||||
</pre><p>
|
||||
Let's see what's going on here. The .text size in the std version is
|
||||
smaller, indicating less inlined functionality. This version of gcc
|
||||
libstdc++ instantiates additional eleven functions totalling 953 bytes
|
||||
just for this one vector type. These functions will become larger for
|
||||
containers with objects, but about 1k in savings that you see as the
|
||||
difference in execuable size is a good measure. The uSTL version inlines
|
||||
everything and calls memblock functions instead.
|
||||
</p><p>
|
||||
1k doesn't seem like much, but consider that you get it for <em>every
|
||||
type of container you instantiate</em>! An int vector here, a float
|
||||
vector here, a bunch of object containers there, and before you know it
|
||||
you are using half your executable just for container overhead.
|
||||
</p><p>
|
||||
But wait, there is more! Let's look at the total memory footprint:
|
||||
</p><pre>
|
||||
% footprint std/tes
|
||||
text data bss dec hex filename
|
||||
3780 632 16 4428 114c tes
|
||||
84445 928 632 86005 14ff5 libgcc_s.so.1
|
||||
527390 720 72 528182 80f36 libm.so.6
|
||||
962481 34816 84664 1081961 108269 libstdc++.so.6
|
||||
1404487 18024 20032 1442543 1602ef libc.so.6
|
||||
2982583 55120 105416 3143119 2ff5cf (TOTALS)
|
||||
|
||||
% footprint ustl/tes
|
||||
text data bss dec hex filename
|
||||
2435 616 16 3067 bfb tes
|
||||
84445 928 632 86005 14ff5 libgcc_s.so.1
|
||||
152800 10408 73248 236456 39ba8 libustl.so.1.5
|
||||
1404487 18024 20032 1442543 1602ef libc.so.6
|
||||
1644167 29976 93928 1768071 1afa87 (TOTALS)
|
||||
</pre><p>
|
||||
As you can see, the footprint for the uSTL version is 44% smaller,
|
||||
saving 1375048 bytes. If you don't count libc, measuring only the
|
||||
C++-specific overhead, libstdc++ loads 1696148 while libustl only 322461,
|
||||
<em>five times less</em>! Finally, most of uSTL's size comes from gcc's
|
||||
support libraries; if you compile uSTL configured <kbd>--with-libstdc++</kbd>
|
||||
option, then you'll see that it only takes up 72322 bytes, of which only
|
||||
23350 are used by .text, meaning that only about a third of the library
|
||||
size is my fault. gcc developers will have to reduce the size of libsupc++
|
||||
before any further size reduction would be practical.
|
||||
</p><p>
|
||||
One final note concerns the current gcc versions, 4.4 and later. gcc
|
||||
developers have decided, for various reasons, to treat the inline keyword
|
||||
as nothing more than a hint to the optimizer, resulting in a lot less
|
||||
inlining for uSTL-using code. You can see which functions fail to inline
|
||||
if you turn on -Winline warning. Back in gcc 3 days there were various
|
||||
parameters that could be tweaked to get the inlining to happen. These no
|
||||
longer seem to work. Because it takes quite a bit of code to make these
|
||||
failures happen, I am unable to submit a gcc bug for it. Simple examples
|
||||
don't exhibit inlining failures and submitting the entire uSTL codebase
|
||||
seems inappropriate. Therefore I've pretty much given up on it. The only
|
||||
solution I can come up with is to just clobber the optimizer over the head
|
||||
with <code>#define inline __attribute__((always_inline)) inline</code>. It
|
||||
is enabled if you configure with <kbd>--force-inline</kbd>. The above
|
||||
examples are compiled with this option.
|
||||
</p>
|
||||
<h2><a name="Contact">Bug reporting</a></h2>
|
||||
<p>
|
||||
Report bugs through the SourceForge.net
|
||||
<a href="http://sourceforge.net/projects/ustl">uSTL project page</a> with the
|
||||
standard bugtracker.
|
||||
</p>
|
||||
<hr />
|
||||
<div class="sffooter">
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img src="style/valid-xhtml10.png"
|
||||
height="31" width="88" alt="Valid XHTML 1.0!" />
|
||||
</a>
|
||||
<a href="http://sourceforge.net">
|
||||
<img src="http://sourceforge.net/sflogo.php?group_id=76798&type=4"
|
||||
width="127" height="37" alt="Hosted on SourceForge.net" />
|
||||
</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
3
extern/ustl/1.5/docs/robots.txt
vendored
Normal file
3
extern/ustl/1.5/docs/robots.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
User-agent: *
|
||||
Disallow: /style/
|
||||
Sitemap: /sitemap.xml
|
||||
15
extern/ustl/1.5/docs/sitemap.xml
vendored
Normal file
15
extern/ustl/1.5/docs/sitemap.xml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>http://ustl.sourceforge.net/</loc>
|
||||
<changefreq>yearly</changefreq>
|
||||
<lastmod>2011-03-16</lastmod>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>http://ustl.sourceforge.net/html/</loc>
|
||||
<changefreq>yearly</changefreq>
|
||||
<lastmod>2011-03-16</lastmod>
|
||||
<priority>0.2</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
27
extern/ustl/1.5/docs/style/default.css
vendored
Normal file
27
extern/ustl/1.5/docs/style/default.css
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
color: black;
|
||||
background-color: #59C;
|
||||
margin: 5mm
|
||||
}
|
||||
div.banner {
|
||||
color: black;
|
||||
background-color: #48B;
|
||||
text-align: center;
|
||||
font-size: 1cm;
|
||||
padding: 1mm;
|
||||
margin-top: -5mm;
|
||||
margin-left: -5mm;
|
||||
margin-right: -5mm;
|
||||
margin-bottom: 5mm
|
||||
}
|
||||
div.motto {
|
||||
color: #159;
|
||||
font-style: italic;
|
||||
font-size: 2mm;
|
||||
margin-top: -5mm
|
||||
}
|
||||
div.sffooter { text-align: right }
|
||||
a:link { color: #238 }
|
||||
a:visited { color: #632 }
|
||||
hr.banner { display: none }
|
||||
28
extern/ustl/1.5/docs/style/ustlstyle.css
vendored
Normal file
28
extern/ustl/1.5/docs/style/ustlstyle.css
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
h1 { text-align: center; }
|
||||
a.elRef, a.el, caption { font-weight: bold }
|
||||
a.code, a.el { text-decoration: none }
|
||||
a.code, a.codeRef { color: #4444ee }
|
||||
dl.el { margin-left: -1cm }
|
||||
div.fragment { width: 100%; border: none; background-color: #eeeeee }
|
||||
div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
|
||||
div.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }
|
||||
div.groupText { margin-left: 16px; font-style: italic; font-size: smaller }
|
||||
td.md, td.mdname1, td.mdname, td.indexkey { font-weight: bold }
|
||||
td.indexvalue { font-style: italic }
|
||||
td.indexkey, td.indexvalue {
|
||||
padding-right : 10px;
|
||||
padding-top : 2px;
|
||||
padding-left : 10px;
|
||||
padding-bottom : 2px;
|
||||
margin-left : 0px;
|
||||
margin-right : 0px;
|
||||
margin-top : 2px;
|
||||
margin-bottom : 2px
|
||||
}
|
||||
span.keyword { color: #008000 }
|
||||
span.keywordtype { color: #604020 }
|
||||
span.keywordflow { color: #e08000 }
|
||||
span.comment { color: #800000 }
|
||||
span.preprocessor { color: #806020 }
|
||||
span.stringliteral { color: #002080 }
|
||||
span.charliteral { color: #008080 }
|
||||
BIN
extern/ustl/1.5/docs/style/valid-xhtml10.png
vendored
Normal file
BIN
extern/ustl/1.5/docs/style/valid-xhtml10.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
18
extern/ustl/1.5/docs/ustl.lsm
vendored
Normal file
18
extern/ustl/1.5/docs/ustl.lsm
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Begin4
|
||||
Title: uSTL
|
||||
Version: @version@
|
||||
Entered-date: @date@
|
||||
Description: A size-optimized implementation of the C++ STL.
|
||||
This implementation of the standard template library
|
||||
reduces template bloat by factoring out memory
|
||||
management functionality from STL containers
|
||||
and using templates for type safety only.
|
||||
Keywords: C++ STL standard template library size optimized bloat
|
||||
Author: msharov@users.sourceforge.net (Mike Sharov)
|
||||
Maintained-by: msharov@users.sourceforge.net (Mike Sharov)
|
||||
Primary-site: ibiblio.org /pub/linux/devel/lang/c++
|
||||
@disttar@
|
||||
Alternate-site: http://ustl.sourceforge.net
|
||||
Platforms: POSIX
|
||||
Copying-policy: MIT
|
||||
End
|
||||
15
extern/ustl/1.5/docs/ustlfooter.html
vendored
Normal file
15
extern/ustl/1.5/docs/ustlfooter.html
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<hr>
|
||||
<address style="align: right;">
|
||||
<small>
|
||||
Generated on $datetime for $projectname by $doxygenversion
|
||||
<a href="http://www.doxygen.org/index.html">
|
||||
<img src="doxygen.png" alt="Doxygen" align="middle" border=0 width=110 height=53>
|
||||
</a>
|
||||
<a href="http://sourceforge.net">
|
||||
<img src="http://sourceforge.net/sflogo.php?group_id=76798&type=4"
|
||||
width="127" height="37" border="0" alt="Hosted on SourceForge.net">
|
||||
</A>
|
||||
</small>
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
12
extern/ustl/1.5/docs/ustlheader.html
vendored
Normal file
12
extern/ustl/1.5/docs/ustlheader.html
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>$title</title>
|
||||
<link href="../style/default.css" rel="stylesheet" type="text/css" />
|
||||
<link href="../style/ustlstyle.css" rel="stylesheet" type="text/css" />
|
||||
<meta http-equiv="Content-Type" content="text/xhtml+xml; charset=ISO-8859-1" />
|
||||
<meta name="Description" content="API and usage description for uSTL, a size-optimized STL implementation" />
|
||||
<meta name="Keywords" content="C++, STL, template, bloat, optimization" />
|
||||
</head>
|
||||
<body>
|
||||
Reference in New Issue
Block a user