Change Log

Introduction

This section is an attempt to document all the changes made to the STLplus library. The change log was instituted after version 1.1 was frozen and made an official version. Therefore only the changes since then have been documented.

The official open-source version of STLplus starts at version 2.0. Earlier versions were internal (Southampton University) versions. I have kept the changes for the pre-open-source versions for those users who are familiar with the older versions and want to know this historical information.

Only the numbered versions from 2.0 upwards are available as downloads. The latest version is only available through CVS. Pre-version 2.0 are not available from SourceForge.

Version 3 of STLplus is based on version 2.7. I'll try to keep bug fixes in track between the two versions, but my intention is to gradually phase out STLplus version 2.

Changes from Version 2.7 to 2.8

Changes to CLI Parser use of Ini Manager

The CLI Parser loads default values from the Ini Manager. However, in previous versions, it was possible for a typo to mean that an option was ignored. I have now added error checking so that all variables in the relevant section of the Ini Manager are recognised as command-line options.

An extra error message has been added to messages/stlplus_messages.txt to report this error.

Changes to Ini Manager to improve error reporting

The Ini Manager now keeps track of which line in the Ini file a value comes from, so that error reporting can report the file name and line number of an error. The method ini_manager::variable_linenumber has been added for this purpose.

Bug Fix in Subprocesses

There was a bug in the quoting code for Windows command-lines which resulted in quote marks being added after every character in a string that needed quoting (i.e. contained special characaters). This has been fixed.

Changes from Version 2.6 to 2.7

Port to MinGW

The MinGW project is a Gnu port to Windows that creates native Windows programs. I always intended to support this platform and believed that STLpplus would work with MinGW unchanged, but only just got round to proving that. It does.

You will need the latest version of the makefiles project since MinGW has only just been added as a target platform.

Rework of ntree

I have done a tidy up of the ntree class, since it's interface was a bit untidy and inconsistent with other STLplus containers.

Iterators are now passed by const-reference to methods rather than by value.

I have removed the comparison operators because comparison of trees is too subjective to build-in this functionality.

I have removed the < operator on iterators because this does not make much sense. The = operator stays though.

I have added both iterator and const_iterator variants of methods where appropriate. Sometimes the old version only had one of the variants.

I now pass iterators by const-reference rather than by value.

Reworked dprintf

The dprintf function and its family - found in dprintf.hpp - is a replacement for sprintf which must not be used because of the buffer-overflow vulnerability that it creates. The dprintf functions write to dynamic std::string buffers and overflow is impossible.

Originally I largely rewrote sprintf to implement these functions, using sprintf for limited cases such as floating-point formatting which I did not want to reinvent and which were safe. However, this denied me access to new features such as Unicode support.

It turns out that both Microsoft and Gnu have implemented safe versions of sprintf. Needless to say, both organisations did it differently and also needless to say, Gnu did it better than Microsoft. So I decided that it was time to rewrite my portable functions in terms of the proprietary solutions.

So, the dprintf function set is now a platform-independent interface to the proprietary underlying functions for performing in-string formatting. They do exactly what the underlying C-runtime does.

One side-effect of this is that now the wstring type can be printed to a std::string via these functions, giving some Unicode support.

Changes from Version 2.5 to 2.6

More typename problems with Visual Studio v6

I have a number of fixes in os_fixes.hpp for the limitations of MSVC v6 and gcc v2.xx when handling the typename keyword. However, I missed some other examples of the problem in other contexts - specifically in the implementation of ntree. These have been fixed by adding two more macros - RETURN_TYPENAME and TEMPORARY_TYPENAME to os_fixes. This has been tested with gcc v2.95 and MSVC v6 SP5.

Added virtual destructors to inferface classes

The interface classes were originally declared with no destructor since the destructor would be empty anyway. However, this has now become a bug in gcc v4. I have added empty virtual destructors to satisfy this requirement.

In my opinion it should be possible to declare destructors abstract (i.e. with no body and with "=0" at the end of the declaration to show that the base class destructor should not be called, as with other abstract methods. However, you can't, so I have declared empty destructors instead.

Fixed bug in CLI parser

The CLI parser can print usage information. However, the logic was wrong such that if there were no default values declared, the usage information would not be printed correctly. This has been fixed.

Redefined friend functions as global functions

Previously it was possible to define a global function as a class friend in one step like this:

class thing
{
  friend bool a_function(const std::string&);
};

However, in gcc v4.1, this has been disallowed and the friend is no longer declared as also a global. I'm not sure I agree with this interpretation of the standard but that is the decision that has been made.

The solution is to re-declare the global function either before or after the class as a global:

class thing
{
  friend bool a_function(const std::string&);
};

bool a_function(const std::string&);

There is no change in the implementation - both declarations refer to the same single implementation of the function.

This change affects a lot of the STLplus headers.

Added line numbers to colourised header files in all the documentation

The HTML user guide includes links to colourised listings for the headers. I have added line numbers to these to make finding things easier.

Fixed bugs stopping Borland compiler from compiling STLplus

A user reported a few bugs in hash.tpp, inf.cpp and string_utilities.hpp that prevented the Borland compiler from compiling STLplus. These were:

  1. missing #include <time.h> in string_utilities.hpp
  2. missing std:: prefix to make_pair in hash.tpp
  3. incorrect throw clause in inf.cpp

All these bugs should be bugs with other compilers too, but somehow haven't been caught. They have now been fixed, so STLplus should now be Borland compatible. However, this is still not a supported compiler because I am limited in how much time I can spend testing different configurations. If anyone is interested in becoming the Borland guy for STLplus, please get in touch.

Fixed bug in os_fixes.h

The header file os_fixes.h contains macros to fix compiler- or operating-system-specific problems. The idea is that the default configuration is Posix compliant, so a Posix build needs no compiler directives to be set. All other builds require compiler directives to select the right set of fixes. However, it turned out that my solution to the typename problem broke my default rule so that the code wouldn't compile at all without compiler directives.

This bug fix restores the intended default behaviour.

Added persistence and print functions for vector<bool>

The STL contains a specialisation of the vector class for an element type of bool. This is because the bool type would otherwise be stored in a whole byte, which is the smallest unit that can be allocated. To make it more efficient, the STL version of vector<bool> packs bools into individual bits of a data word.

This is all very well, but the class does not behave exactly like a vector, because bool cannot be returned by reference. So my persistence functions did not work correctly with this class. To solve this problem, I have written special dump and restore functions for vector<bool> which also packs 8 elements into a byte when writing the data structure to a file.

Incidentally, I realised that there really needed to be a special print and to_string function in string_utilities.hpp as well, so I added those too.

Fixed bug in MacOS X (a.k.a. OSX) port

There was an old #ifdef MACOS block in tcp.hpp which was preventing the TCP classes from building on OSX. This was removed - OSX is now a Posix-compliant port and threfore requires no special compiler fixes. Apparently, according to an OSX user, this showed up when using gcc v4 which clearly has tighter compliance checking - STLplus already built OK on OSX with earlier versions of gcc.

Added function for performing platform-specific comparison of path strings

I have aded a function for comparing file paths to file_system. This is just a string comparison, but is case-sensitive on Unix and case-insensitive on Windows. Therefore I have encapsulated this platform-dependent feature into a platform-independent interface.

Made file_system functions more tolerant of missing/present trailing separator

The separator character ('/' or '\') is handled in a platform-specific way within the file_system functions, but should not be manipulated by the programmer except via these functions if platform-independence is required. The convention is that paths representing folders have a trailing separator to show that they are folders. In previous versions, this was not consistently done and furthermore, some functions failed if the separator was present.

The file_system functions have been reworked so that the trailing separator is consistently added and furthermore all functions should now work correctly with or without the trailing separator.

In the translate function from string_utilities, made the "to" default to the empty set

In the past, the translate function required three parameters, the string to be translated and then the "from" and "to" sets. However, a common usage is to have an empty "to" set, in which case the translation simply deletes all characters in the "from" set. I have added a default value to the "to" set so that it need not be specified in this common case where the empty set is required.

Fixed bug in string processing of command lines in subprocesses

The subprocess classes take a command line argument which is a string that is then passed to the operating system as a vector of arguments. The string processing that converts the string to the vector is based on the equivalent functionality built into Unix-like shells. This means that special characters in double-quoted strings have to be escaped with '\'. However, in single-quoted strings they do not. This seems better, but leaves the problem that the single-quote character itself cannot be contained in a single-quoted string.

This slightly quirky behaviour is well-known so was kept for the subprocess functions. However, I got the prioritisation wrong so that special characters needed escaping in single-quoted strings as well. I have now fixed this.

Changes from Version 2.4 to 2.5

Fixed compatibility problem with gcc v4

In some headers I use friend class xxx to do two things - create a forward declaration of class xxx and also make that class a friend of the current class. It turns out that in gcc v4 this doesn't work - you have to make a forward declaration separately. All the headers where I used this shortcut have now been changed to have a separate forward declaration:

The old way:

class yyy
{
  friend class xxx;
};

The new way:

class xxx;

class yyy
{
  friend class xxx;
};

This was only a problem where a forward declaration of class xxx was needed and not for any other friend declarations.

Fixed bug in file_system headers

The headers for file_system includes some pre-defined values for access permissions for use with the file_set_mode function. The read_mode value had somehow been given a double-underscore to make it read__mode - which is wrong. It has been corrected.

Fixed documentation for iterators

The documentation for iterators used in hash, ntree and digraph was out of date - very out of date - since it referred to the original iterator design prior to version 1.2. The redesigned iterators have three modes - null, end and valid. A null iterator is uninitialised, an end iterator is initialised but must not be dereferenced because it is past the end of the structure and a valid iterator is the only one that can be dereferenced. This has now been properly documented for the three container classes that use iterators.

Changed parameter type of display_time

The display_time function in string_utilities.hpp used to take an unsigned argument which was an elapsed time in seconds and display it in human readable form. However, the convention is to use type time_t for this purpose. The function's interface has been changed to take a time_t parameter.

Rationalised macros for fixing typename problem

There are problems with using the typename keyword. Technically, if you use a type member of a template class (i.e. a type declared within the template class by a local typedef), you need to tell the compiler that it is a type name. This is because the compiler cannot work out whether a member is a type, a method or a data field at compile time. However, support for the typename keyword has traditionally been incomplete in both gcc and Visual Studio. I have used macros defined in os_fixes.hpp to try to resolve this issue. The macros add the keyword for compiler versions that require it and omit it for compiler versions that do not support it.

This fix has been in place for some time, but this version fixes the problem so that STLplus compiles warning-free on versions 6, 7 and 8 of Visual Studio.

There are three places where typename keywords cause problems:

  1. in a typedef where a template class's member type is being mapped onto a type definition with in another template class or function

          e.g. template<typename T> fn () {
                 typedef typename someclass<T>::member_type local_type;
                         ^^^^^^^^
    

    This situation is handled by the macro TYPEDEF_TYPENAME.

  2. in a function parameter declaration, with similar rules to the above

          e.g. template<typename T> fn (typename someclass<T>::member_type)
                                        ^^^^^^^^
    

    This situation is handled by the macro PARAMETER_TYPENAME.

  3. in instantiating a template, the parameter to the template, with similar rules to the above

          e.g. template_class<typename someclass<T>::member_type>
                              ^^^^^^^^
    

    This situation is handled by the macro TEMPLATE_TYPENAME.

Note that the typename keyword is only required when the type is of this form - a member of a template class.

Rationalised macros for Microsoft Windows build

Microsoft seem to define only one of two different macros _WIN32 or _WIN32_WCE for different versions of Windows (I don't know the exact details, this has been reported to me by a user). This breaks the usual convention of defining one master macro and then a second one as well for variants. Anyway, that's their choice. I have rationalised this by defining the macro MSWINDOWS in os_fixes.hpp which is present if either of the Microsoft macros is present. This new macro is then used throughout STLplus for all Windows-specific code.

Removed debug trace code from STLplus

I have removed all debug code from STLplus so that the debugging macros in debug.hpp only trace debug information for user's code. This is more user friendly in that it means the user isn't expected to understand debug trace information for code written by me. However, I appreciate that it may make it more difficult to find bugs in the STLplus code itself. I am making this change now because STLplus seems to me to be becoming mature code and bug reports seem to be dwindling. I guess I may regret that comment any day soon...

Changes from Version 2.3 to 2.4

Fixed bug in triple's default constructor

The default constructor for triple (i.e. triple::triple()) was not calling the default constructors for its element fields. Thus they were not being properly constructed.

This problem has been fixed.

The same problem with foursome was also fixed (since foursome is a cut-paste-n-edit of triple).

Added Foursome

This is the next in the series:

This was originally called quadruple but both this and quad caused naming conflicts on Solaris. So, I have change the name to foursome.

There is no documentation for foursome, but if you use pair which is used in the STL class map, then the use of foursome will be obvious.

Bug fix to Ini Manager to handle empty values

This bug fix is a response to the following bug report:


I do have a problem that with every version, I have to change line 339 of ini_manager.cpp from this:

while (isspace(value[value.size()-1])) 

to this:

while (!value.empty() && isspace(value[value.size()-1])) 

Otherwise, it will crash on empty values.


I have changed the code to support empty values.

Bug fix in restore routine for pointers

A response to the following bug report:


I wanted to raise a question about a possible bug in the implementation of restore_pointer() and restore_interface() functions.

The way these functions are written, the object if first restored and then the appropriate address is added to the address map in order to enforce isomorphic persistence. In my opinion, the address needs to be added first before performing a restore on the data. This is because in self-referencing structures (in particular circular link lists), if we have not added the address to the map before restoring the data we will not be able to maintain isomorphic persistence.

For a simple example, consider a single circular link list with only one element and its next pointer points to itself. While restoring this, we will try to restore contents of the element. Ideally we should enter the address into the map first and then restore contents, this way while restoring the next pointer we will understand that it has already been restored (or more accurately in this case it is in the process of being restored). But if we do the addition of the address into the map later on we cannot register the fact that the element has been (or is being) restored since the address is not in the map.

With respect to the code, in persistent.tpp, for restore_pointer(), look at the else part of the control flow. We do

data = new T();
restore(context, *data);
context.pointer_add(magic, data);

In my opinion, it should be

data = new T();
context.pointer_add(magic, data);
restore(context, *data);

I do not know if the reason for choosing the former was because it avoids some other obscure problem that the latter does not, but I cannot think of any such thing at the moment.


My response was:


I believe that your reasoning is right. I think this bug got through because I tend to avoid self-referencing structures because they so often end up causing memory management problems. However, the library should work with them despite this.

So, I will make the change that you suggest. I suspect that I also need to check some other routines as well, such as the code for smart pointers.


It turned out that there was a need to make changes to the smart pointer persistence routines as well as the pointer routines.

Changes from Version 2.2 to 2.3

Compatibility for gcc v3.4

This version of the gcc compiler introduces much more restrictive support for templates, by which I mean that the compiler is much less tolerant of "slack" declarations. It also reduces the usage of forward declarations of structs and classes. I have reorganised STLplus and added a lot of typename keywords to resolve these issues. This version is now compatible with gcc v3.4, at least according to my tests. However, I have found that compilation errors only show up when a template method is actually used in code - and there are many template methods which are not yet tested by my test pack. Please report any problems with missing typename keywords.

New smart-pointer classes

A collaborator - known to all as DJDM - has supplied some variants of the smart-pointer classes which have a more pointer-like behaviour. There are three different classes - simple_ptr is a simple pointer to any object copyable through its copy constructor; simple_ptr_clone is a simple pointer to an object copyable via a clone method; and simple_ptr_nocopy is a simple pointer to an obbject that cannot or should not be copied.

Changes from Version 2.1 to 2.2

Changed license terms

I have changed the license from the Lesser Gnu Public License to the more relaxed and more open BSD License. This makes the STLplus library usable by a wider audience and with fewer restrictions on how its used. I still hold the copyright and disclaim responsibility for any errors, as is normal for all software now.

Fixed CLI Parser Throw Clauses

The CLI Parser interface had throw clauses that claimed that constructors could only throw the cli_mode_error exception. In fact they can throw others and these have now been added. For example:

cli_parser::cli_parser(char* argv[], cli_parser::definitions_t definitions, error_handler& errors)
  throw(cli_mode_error,error_handler_id_error,error_handler_format_error);

Reworked Persistence of Cross-References

In a number of components (specifically: digraph, ntree) it is possible to make iterators persistent provided the object (for example the digraph) has been dumped before any iterators are dumped. I have generalised the code for this and moved the generalised code into persistent.cpp. The functionality is the same.

Added folder_all Function to file_system

The folder_all function returns a vector of all the files and directories in a specified directory. This is returned as an STL vector of STL strings.

Allowed Drive Letters in Cygwin Paths in file_system

As a rule, the Cygwin (a Unix emulation running under MS Windows) build of file_system uses Unix conventions for paths. However, the underlying Cygwin system can handle Windows drive letters, so I have added this capability to the file_system functions.

Made the Hash Class More Compatible With Map

The old hash::insert method returned the iterator to the inserted object. However, this is incompatible with map::insert which returns a bool/iterator pair. The interface to hash was always intended to be compatible with the STL map, so it now returns the same pair:

std::pair<iterator, bool> hash::insert(const value_type& value);

The map class has a map::count method which returns a count of the number of objects associated with a key. It returns 0 for not present and 1 for present - this is really useful in multimap. However, for compatibility I've added it to the hash class:

size_type hash::count(const K& key) const;

It is possible to remove all data from a map with the map::clear method. I've added an equivalent hash::clear:

void hash::clear(void);

Renamed Time Manupulation Functions in time.hpp

The old names all had the prefix "time_". This was a poor choice anyway and had the additional problem of causing name conflicts on some operating systems. In all cases I have renamed the functions with the prefix "localtime_". This is more consistent with the intent of the functions and the definition of the concept of localtime in Unix.

Fixed Bug in persistent.tpp

I had created the dump/restore_multimap/set functions by cutting and pasting from the dump/restore_map/set functions. I had forgotten to edit them to change the scope names of the iterators. This led to compilation errors. I have now fixed these bugs. Thanks to Elias Yanna for pointing this out.

Changes from Version 2.0 to 2.1

Added reporting of INI files to cli_parser

The cli_parser now stores the set of INI file names used in its initialisation. This list is produced as part of the usage method's output, so that users can see which files they are using.

The cli_parser usage method now looks like this:

usage:
	plibrary { arguments }
arguments:
	-[no]help               # this help!
	-create <name>=<path>   # create a library called <name> in directory <path> and add to the list
	-add <path>             # add the library at <path> to the library list
	-remove <name>          # remove the library <name> from the library list
	-delete <name>          # delete the library called <name> and its directory
	-work <name>            # make <name> the current work library
	-lock                   # lock the work library
	-unlock                 # unlock the work library
	-tidy                   # tidy (erase) all out-of-date units in work
	-[no]verbose            # verbose listing (list units in each library)
	-[no]version            # display product version
values:
	-version : from ../../phoenix/config/phoenix.ini
	-help : from command line
configuration files:
	./phoenix.ini (not found)
	../../../phoenix.ini (not found)
	../../phoenix/config/phoenix.ini

Note the set of configuration files at the end.

This change also added extra messages to the file messages/stlplus_messages.txt.

Added adjacent_arcs method to digraph

The digraph class had a method for getting the arc that connects to nodes - its called adjacent_arc. However, there may be more than one arc connecting two nodes, so I have added the plural form adjacent_arcs which gets the set of all arcs connecting two nodes.

More information in error_handler exceptions

I've added more text to the exceptions thrown by error_handler for better diagnostics. This text can be obtained by calling the what method of these exceptions which are derived from std::exception.

Added install path function to file_system

The directory containing the current program can be obtained by calling the install_path function. This function takes as its argument the argv[0] parameter from the main function.

Added test in library_manager for successful saving of the INI files

One of the options in the library_manager is to store library mappings in INI files managed by the ini_manager. Previously, the save method of the ini_manager could fail to store the library mappings (for example due to a read-only file) and the library_manager would not detect this. Now, the library_manager save_mappings method returns false if this fails.

Added portability fixes for Borland compiler to os_fixes

This header should be included as the first include in every source file to eliminate compiler-specific portabilty issues.

I've disabled some of the more irritating warnings from the Borland compiler by adding pragmas to os_fixes.hpp.

I've also mapped the Borland __FUNC__ macro onto the more generic __FUNCTION__ macro used by gcc and Visual Studio.

Tidied up exception throwing code in persistent

The way I was handling exceptions in the persistent functions for polymorphous types was simply clumsy. I've reworked it to be cleaner.

Added recognition of the Borland compiler version

The stlplus_build function in stlplus.hpp returns a string representing the build parameters (OS, compiler and compiler version). This now recognises the Borland compiler.

Class quadruple removed

Class quadruple is a continuation of the sequence pair/triple. However, I discovered that the name caused a conflict on Solaris. The name quad is also taken. For the moment I have simply removed the source files. I expect to reintroduce this class when I find a non-conflicting name.

Improved the display_bytes function

The display_bytes function in string_utilities displays a byte count in a user-friendly form (e.g 2.1MB). I've reworked it to give more consistent precision across the range.

Tidied up TextIO

TextIO was a bit of a mess because of many additions over the years. I have done a major tidy up and as part of this have merged the textio_buffers.hpp and .cpp files into the main textio.hpp and .cpp files. This will only effect you if you had created new TextIO derivatives yourself.

Added Test for Byte Order to os_fixes

The new function little_endian has been added to os_fixes.hpp. This can be called to determine the byte ordering of a CPU. The issue is explained in the documentation for data persistence.

Portability work

A number of changes have been made to make the library more portable. These are:

Incremented the Data Persistence Version

The changes to inf to make it portable have changed its data persistence format. The persistence format version has been incremented to 2 as a result. Version 1 files will still be read correctly. New files will be written as version 2.

Changes from Version 1.4 to 2.0

Move to SourceForge

The version was incremented from 1.4 to 2.0 to make this the official first version of the library on SourceForge.

Change of License

I decided that the GPL was too restrictive for this library. I have changed the license to the LGPL.

Changes from Version 1.3 to 1.4

Bug fix - removed assumption that char is signed

I had problems with native builds on Windows using gcc that forced me to use unsigned char as the default type for char. This in turn uncovered a subtle bug in inf.cpp and a common-mode bug in string_utilities.cpp where char was assumed to be signed. Fixed by using an intermediate int to avoid char completely.

Preparation for Open Source Publication

All source has been checked to ensure it has correct Author field and a License field has been added. The license has been added to the documentation in file license.html. I have chosen the GPL as the most appropriate license for now although I may downgrade this to the Lesser GPL if the GPL proves too onerous to users.

16 January 2004 - Version 1.4 frozen

This version has been frozen as an official release 1.4. This is the last release hosted within ECS. The version number will be incremented to 2.0 which marks the start of the SourceForge hosted open-source version. As the changes above show, some of the preparation work for the open-source version are part of this version.

Changes from Version 1.2 to 1.3

Error Handler Message Formats can now be in the Message File

In previous versions, the message formatting strings were hard-coded into the error_handler and could only be overridden from C++ source code. I have now added the ability to ovverride the format strings from within the message file itself.

You can now go up many levels of directory in one call

The folder_up function in file_system.hpp now takes an optional second argument specifying how many levels to go up. The default is 1 for compatibility with older versions.

Added new display functions for bytes and time

I have added two extra functions to string_utilities.hpp

This function is now used to display elapsed time in the CPU timer.

Persistent Iterators Added

I have added persistence functions for the iterators in digraph and ntree only. I have not added them to hash because it is bad practice to store iterators to hash table elements (they can be invalidated by rehashing at any time).

I have not added persistence of iterators for STL types because there is insufficient access available to implement them.

Added new file system functions

I've added the following functions to file_system.hpp:

folder_set_current
Allows the current working directory to be changed
folder_elements
splits a folder path into its string elements
filespec_elements
as above for a filespec

Added sleep function

In os_fixes.hpp I have added the function sleep(seconds) for Windows. This is a standard system function on Unix, so this function makes it portable to Windows.

Fixed a bug in error handler

The problem was with context messages. The idea of context messages is that, if you are doing something recursive, an error can be meaningless unless it is given some context - such as the key parts of the call stack. So, the idea is that you push a context message into the error_handler's context stack as you go down the recursion. Then, when an error occurs, the error message is supported by contextual messages that make it more meaningful.

It turns out that most of the time, contextual messages aren't used. If no errors occur during the recursion, no messages get printed and so no context messages are used.

The bug was that, if you used the context functions (push_context, auto_push_context), the contextual message was created at the time of the call. If the message was a positional message, this caused the source file (e.g. a VHDL source file) relating to the context to be loaded. Since most of the time the contextual message wasn't used, this was causing a significant and unnecessary overhead,

The fix means that the contextual messages - and the supplemental messages - are generated as late as possible to avoid this overhead.

Fixed a conceptual error in error handler

The concept of an auto-context was a bit wrong in the original design of the error handler.

The idea of an auto-context is that you push the context stack at the start of a block and an object stores the fact that you have done this. At the end of the block the object is destroyed and this destruction automatically pops the context stack. This means that it is easy to match push/pop pairs even in the presence of multiple exit points or even exceptions.

In the original design, the object was a class which stored the state of the error handler prior to the push and restored it on destruction. So far so good. However, it had to be declared before use and then passed as a parameter to be filled in:

error_handler_context context;
auto_push_context(context, ...);

Not too bad, but clumsy. The real problem was that if a temporary copy of the object was made for any reason, it would be destroyed prematurely and cause the context to be popped prematurely.

The solution is to rework the concept so that the object is pointed to by a smart pointer. Thus, the object is not destroyed until the last copy of the pointer is destroyed, thus eliminating the above problem.

The data type of the context object is error_context_body and should never be used directly. The pointer type is called error_context and this is the type that should be used.

This redesign means that assignements can be used - these weren't possible before because assignments create temporaries. Therefore the auto_push_context methods have been redesigned to return the context:

error_context context = auto_push_context(...);

This is much better C++. Note that I have also simplified the name. Since you need to rework any code using auto-context then I thought this was an opportunity to make the type name shorter.

Reorganised error handler

In the process of fixing the two problems above I did a reorganisation of the error handler to hide more of the implementation from the user. Internal data types are now mostly hidden.

I also renamed error_handler_position as error_position (but defined a pseudonym of error_handler_position for backwards compatibility). I renamed error_handler_context to be error_context. This does not have a pseudonym. Because of the fix above, the use of the type has changed. It seemed to me that any code using the type would need reworking anyway, so renaming the type was no big deal.

4 November 2003 - Version 1.3 frozen

This version has been frozen as an official release 1.3 and the working version incremented to 1.4.

Changes from Version 1.1 to 1.2

Fixed #include "os_fixes.hpp" throughout

The intention is that every file should have os_fixes.hpp included as the very first include to ensure portability between compilers. This intention hadn't been maintained over the past few months. This fix ensures that every header in STLplus includes os_fixes.hpp first.

Added No-Copy Variant of smart_ptr

A third variant of a smart pointer called smart_ptr_nocopy has been added. This is for managing classes that cannot or must not be copied.

I have also modified the library_manager and the TextIO subsystem to use this class.

Added Convenient short-cut functions for Persistence

I have added short-cut functions to the persistence functions that act as wrappers to do the whole job of dumping or restoring a class in one function call. For example, dump_to_file will perform the whole process of creating a dump context with an output device of a file and then dumping a data structure to that file.

These functions are templates so that they can adapt to the class being dumped.

Added Installer Functions for Persistence

When using persistence of polymorphic types you have to register each polymorphic subclass with the dump or restore context. When writing software I tend to wrap up all the registrations into a function. So I have added a register_all method to the dump and restore context classes that takes such an "installer" function as its argument. This is just a simple shortcut that made the writing of the short-cut functions mentioned above possible.

Made one-argument constructors explicit

A one-parameter constructor is considered to be a type cast and may be called implicitly by the compiler. I have had problems where I used the wrong type in an expression (or even the wrong const-ness) and ended up with a temporary library_manager or ini_manager object being created because these classes have one-parameter constructors. This was definitely unwanted behaviour. The problem is that C++ compilers are over-enthusiastic about trying to find implicit casts like this.

The solution is to make the constructors explicit. I have done this for the library_manager and ini_manager so far. Note also the documentation on the infinite precision integer type inf which has explicit constructors throughout - this was done some time ago to avoid the same problem, at the cost of significant utility in using the package - unfortunately the compiler became over-fond of creating infs where they were not wanted.

Solaris Support

A slight adjustment was required to the includes of system headers in order to build STLplus on the Solaris operating system. This has no effect whatsoever on the users of the library.

Solaris is now a supported port for STLplus. It requires -DSOLARIS to be defined in the compilation phase.

You also need to link with the socket library (-lsocket with gcc). This is done for you if you're using my make system.

Added the Interface Concept

I have started to use the Java concept of interfaces in the STLplus library.

Made the template containers compatible with Visual Studio version 7.1 (.NET 2003)

This version of Microsoft's compiler is stricter about the use of the typename keyword. Where a method parameter is a type defined within the template class, this version of VS requires the typename keyword to be used. To prevent problems with other compilers I've used the macro PARAMETER_TYPENAME to insert this only for VS7.1.

Created compiler-specific macros in os_fixes.hpp

I have added some macros to handle the different "fussiness" of different compilers over the use of the typename keyword. As mentioned above, Visual Studio 7.1 requires them in method parameters. Gnu's gcc version 3 requires them in typedef declarations where the type being referenced is a template instance. See the digraph or ntree source code for examples.

These differences have been centralised so that all incompatibilities between compilers are handled by declarations in os_fixes.hpp.

Complete Rework of Conversions from Numeric Types to their String Representations

This affects string_utilities and inf.

A couple of bugs were found in to_string for numeric types. There was also a legacy problem with the interpretation of the alignment and padding parameters. I have reworked the code to eliminate the bug and whilst doing it I have rationalised the interface.

I have also ensured that the reverse conversions to_int, to_uint etc. are compatible with the to_string conversions. This applies to all numeric types defined by C++ and also my inf type.

The old interface was:

std::string to_string(type value, unsigned radix, radix_display_t display,
                      alignment_t alignment, unsigned width, char pad);

The problem is that the field width and alignment do not belong here. I redefined the width to mean the number of digits in the result and eliminated the alignment and padding parameters. The new interface is:

std::string to_string(type value, unsigned radix, radix_display_t display, unsigned width)
   throw(std::invalid_argument)

The function will throw the exception if you specify a radix outside the range 2-36 or if the display parameter is not a valid value.

The reverse conversions can also throw an exception:

type to_type(const std::string&, unsigned radix = 0)
   throw(std::invalid_argument);

The exception will be thrown if the string is not a valid integer format.

I've also removed the ability to set alignment and padding parameters for integers in TextIO.

Reworked the min/max Problem

The STL defines template functions std::min and std::max. Microsoft defines macros min and max. Visual Studio didn't provide std::min and std::max prior to version 7. Now both templates and macros are defined. This can cause portability problems. There is an attempt to fix this in os_fixes.hpp but I have also defined template functions minimum and maximum that you can use to avoid this issue completely.

Minor Mods to TCP

Users (namely ACW and DJDM) have added two things to the TCP classes:

There's also a bug-fix for Windows.

Added Quadruple

This is the next in the series:

Self-Checking Iterators

The iterators for the STLplus container classes digraph, hash and ntree now have consistency checking code to detect common iterator misuse. Many of the methods in these classes can now throw one of three exceptions - wrong_object, null_dereference and end_dereference. See the documentation on exceptions for an explanation.

Extra File Operations

I have added the functions file_copy and file_move to file_system.hpp. The file_copy function, as it says, copies one file to another. The file_move function tries to rename the old file to become the new file, but if that fails it copies the file and deletes the original.

Subprocesses and signals

The subprocess classes used to treat the case of the child being interrupted by a signal as an error. This messed up the error_text function because the status value was not a proper error number. It seems to me that this case is in fact an exit not an error - the error handling is supposed to be related to errors in the parent trying to manage the child, not errors in the child. so I now set the exit status to the number of the signal. This means that the subprocess appears to exit with non-zero status.

You can now get the error number as a number, not just as a string.

6 June 2003 - Version 1.2 frozen

This version has been frozen as an official release 1.2 and the working version incremented to 1.3. The differences reported by CVS amounted to 10k lines of output!