STLplus
Review and upgrades
by Curtis Krauskopf
STLplus
is an eclectic collection of STL C++ components. The
areas covered in STLplus range from the mundane (trimming
strings) to advanced (directed graphs, hash tables and
file management). Figure A shows
the broad categories covered by the library and the
solutions provided in each category.
STLplus is cross-platform compatible.
Figure
A |
|
STLplus contains
over 12,000 lines of algorithms, STL containers
and utility functions in 24 modules. This image
is a composite of the STLplus HTML documentation. |
Installation
According to Andy Rushton, the creator and maintainer
of STLplus, "The reason I keep hammering on
about this ease of use is that I've had nightmare scenes
with other code libraries which require mind-bogglingly
complicated procedures to build and use them (e.g. STLport
and the Boost libraries - for all I know these are all
superb, but if I can't build them, how am I to find
out?). So I want to let you know that STLplus is not
like this - it is trivially easy to build."
[1]
He's right. STLplus is easy to install and build.
Although there isn't a Borland project in the distribution,
the STLplus source code includes __BORLAND__
conditionally compiled code. It seems to me that STLplus
was, at some time in its past, Borland compiler compatible.
I created a Borland project by converting the Microsoft
Visual C++ project. In Borland C++Builder 6, I used
the wizard. Unfortunately, the wizard-generated
project gave me many compile-time errors in Borland's
stdlib.h in the __MFC_COMPAT__
section. From experience importing other libraries,
I've learned that tracking down compile-time errors
like
E2316 '_itoa' is not a member of 'std'
can eat hours (or an entire day).
My favorite solution when I encounter a problem like
this is to rebuild the entire project from scratch.
A quick audit of the files that the wizard placed in
the project told me that all of .cpp files in the STLplus
~\source\ folder were
used. The conditional defines looked normal: WIN32;_DEBUG;_LIB;_MBCS
Creating
a static library project
First, I create an STLplus\IDE\BCB60
folder. The open-source libraries I use follow
this same pattern so I don't have to hunt for the project
files. Separating the Borland files from the distribution
files makes incorporating future upgrades (of either
the project code or the compiler I'm using) easier too.
I create a project group with (see
Figure B).
Figure B |
|
Start creating a static library
by first creating a new Project Group. Then choose
the Library icon from this new items dialog
to create the library. |
A static library is added to the project by using
.
Both the static library and the project group default
to my CBuilder6 folder
but I don't worry about that now.
Next, I open Windows Explorer and navigate to the
STLplus\source folder.
Sorting the files by type puts all of the .cpp files
together. At that point, it's easy to highlight the
.cpp files and drag them
over to the Project1.lib
in the Project Manager panel.
Then I save the Project Group and static library in
the IDE\BCB60 folder I
previously created. I use appropriate project and unit
names called STLplus.
Compiling this project gives a compile-time error
in string_utilities.hpp:
'time_t' cannot start a parameter declaration.
For the Borland compiler, time_t
is defined in the <time.h>
header. I added the code highlighted in Figure
C near
Figure C |
|
STLplus needs to include the
time.h header file to define the time_t
symbol. |
the top of the string_utilities.hpp
file, after the last #include.
Encouraged by my initial compilation success, I press
forward and encounter a new compile-time error:
digraph.tpp(244): E2293 ) expected
This tells us a couple things. STLplus uses .tpp files
for template header files. I've never seen that extension
used in a C++ project but I like that idea and I might
use it in my own projects. Previous experience with
E2293 tells me that the error is actually earlier on
the line – in this case it’s an undefined
PARAMETER_TYPENAME symbol.
Grepping for PARAMETER_TYPENAME
shows that it's conditionally defined in os_fixes.hpp.
Definitions for PARAMETER_TYPENAME
are provided for GNU C++ and Microsoft Visual Studio
but not for Borland C++. I added the code in Listing
A to os_fixes.hpp
on line 216 (before the 'problems with missing functions'
comment).
Listing
A |
#if __BORLANDC__ >= 0x0560
#define TYPEDEF_TYPENAME typename
#define PARAMETER_TYPENAME typename
#define TEMPLATE_TYPENAME typename
#endif |
Add this code to os_fixes.hpp |
The next compile-time error complains that the library
is too large. After some experimenting, I found that
setting the library page size to 0x0080
fixed that problem. To change the library size:
- Open the Project Options for the STLplus library
by using the shortcut key .
- Choose the TLIB tab
- Change the Page Size from 0x0010
(the default) to 0x0080
The next build is successful. Wow -- only two source
files and one default in the compiler had to be changed.
That's not too bad for a library with over 12,000 lines.
Warnings
Most of the compile-time warnings complain about initialized
data in the header that prevents precompilation from
working. A warning in inf.cpp
complains that a throw type is different than the type
promised in the function declaration. In inf.cpp
(line 1423), change the exception from persistent_dump_failed
to persistent_restore_failed.
While you're there, change the error message on that
line too. The distribution says inf::dump
but the error message should be inf::restore.
The next build successfully creates the STLplus.lib
file with only warnings about creating pre-compiled
headers.
Hash table example
Listing B shows an example
hash table. I purposely kept the hashing algorithm simple
to force hash table collisions. The comment says that
it’s the world’s worst hashing algorithm
but that’s not true. The worst hashing algorithm
would return random numbers for the same string.
Listing
B |
#include <iostream>
#pragma hdrstop
#include <hash.hpp>
using std::string; // to make
using std::cout; // this listing
using std::endl; // narrower
// World's worst hashing algorithm
struct hash_string {
unsigned operator()
(const string & s) const
{ return 5; }
};
int main(int argc, char* argv[]) {
hash<string, string, hash_string> symbols;
symbols["alpha"] = "a";
symbols["bravo"] = "b";
cout << "alpha = ";
cout << symbols["alpha"] << endl;
cout << "bravo = ";
cout << symbols["bravo"] << endl;
if (symbols.present("charlie"))
cout << "found charlie" << endl;
else
cout << "charlie not found" << endl;
symbols["charlie"] = "c";
if (symbols.present("charlie"))
cout << "found charlie" << endl;
else
cout << "charlie not found" << endl;
return 0;
}
// Expected output:
// alpha = a
// bravo = b
// charlie not found
// found charlie
|
Hash Table Example |
Compiling this example uncovered a compile-time problem
in hash.tpp: make_pair
was undefined. To fix this problem, I inserted std::
in front of make_pair
on line 499:
return std::make_pair(hash<K....
Pros and cons
The library's code is very well organized. For example,
all of the operating system specific code is in the
os_fixes.hpp file. Users
can choose to include stlplus.hpp
(which defines everything) or they can include specific
.hpp files, such as hash.hpp
as shown in Listing B.
The code is well written with copious helpful comments.
Some developers will dislike the CVS files that are
included in the distribution because they might interfere
with the developer's revision control system. A bigger
problem is that there are no unit tests and there are
no examples (other than the snippets and few examples
provided in the documentation).
The documentation is comprehensive and it's written
in HTML. Every module has an introduction, a colorized
C++ header, and details about using the public methods.
The cross-reference is poor and the documentation for
at least one module (library_manager) is unfinished.
A library this large needs excellent documentation.
The main problem with the documentation is that it tries
to be a reference manual and a user manual simultaneously.
The documentation fails as a user manual because detailed
examples are not provided and it fails as a reference
manual because summaries and cross-references of the
module's functionality are not provided in all cases.
The size and scope of the library is large but the
Borland linker is smart enough to include only the portions
that are really needed. I have not experienced significant
code bloat from using the File System Access and String
Formatting modules.
The os_fixes.hpp disables
some Borland-specific warnings that I consider to be
important. Lines 45-70 in os_fixes.hpp
very clearly document which warnings are disabled. This
is really a case of comment-creep because some of the
warnings don't need to be disabled anymore. The W8022
and W8060 warnings (virtual function in a base class
is overridden and possible incorrect assignment respectively)
are not problems in the STLplus code anymore. The other
two warnings (W8008 for condition always true and W8066
for unreachable code) only appear when compiling the
.cpp files. Because the header files are unaffected,
I've chosen to comment-out the pragmas that disable
all four of those warnings.
My experience with STLplus is that I focus on three
or four of the modules and use the others when I have
a special need. STLplus is very similar to a Swiss Army
knife in that you use two
or three of the blades almost all the time and use the
other blades on rare occasions for special purposes.
License
STLplus uses one of the most generous licenses I've
seen. To quote Andy Rushton, "I don't subscribe
to the idealism of some open-source advocates who claim
that open-source software should only be available to
other open-source developers. I want this library to
be used by anyone and everyone, well except intellectual
property thieves and litigious idiots. There are therefore
no restrictions saying you have to make your products
open source as well because I don't believe in that.
If you wish to use this library in an open source project,
great. If you wish to use it in a closed-source commercial
product, equally great." [2]
I wish more open-source developers were as open-minded
about the free distribution of source code.
VCL overlap
STLplus does not provide any GUI interfaces, database
connections or interfaces with user or system events.
The overlap with VCL is mostly limited to filename and
path name manipulation functions. The STLplus TextIO
module provides powerful text, file and string files
that rival the LoadFromFile
and LoadFromStream methods
in the TStrings class.
The STLplus persistent methods and string manipulation
functions duplicate some functionality in the VCL classes
too. However, overall there is very little functionality
overlap between STLplus and VCL.
Availability
STLplus is available at http://sourceforge.net/projects/stlplus
Borland project files, the Borland-specific changes
to STLplus and three example programs using STLplus
version 2.5 are available at the STLplus
BCB Patches Download page.
Conclusion
STLplus is a large library of C++ functions, algorithms
and STL containers. The only commonality between the
modules is the use of the Standard Template Library
as the basis of the building blocks. The modules have
such a broad range of functionality that at least one
module will be useful to most developers, even on small
projects.
Recommendation
Get STLplus
and the STLplus
Borland-specific patches. The STLplus code is well-written
and it provides many examples of creating STL containers
and using STL templates. Even though the library is
enormous, the Borland C++ Builder linker removes the
unused code so your executable will not bloat from using
one mundane function. The specialized header files (such
as hash.hpp) keep the
compile-times down as well. Most coders will use one
or two of the modules but having the other, more esoteric,
modules available can result in having the right tool
at the right time.
References
- "Building and Using the STLplus
Library
STLplus documentation:
~\docs\building.html
- "License Agreement
STLplus documentation:
~\docs\license.html
Contact Curtis at
Curtis Krauskopf is a software
engineer and the president of The Database Managers (www.decompile.com).
He has been writing code professionally for over 25 years. His prior projects
include multiple web e-commerce applications, decompilers
for the DataFlex language, aircraft simulators, an automated Y2K conversion
program for over 3,000,000 compiled DataFlex programs, and inventory control projects.
Curtis has spoken at many domestic and international DataFlex developer conferences
and has been published in FlexLines Online, JavaPro
Magazine, C/C++
Users Journal and C++ Builder Developer's Journal.
Popular C++ topics at The Database Managers:
|