Updated 00/03/15
Sun WorkShop(TM) 6 Tools.h++ 7.1.0 Readme



Sun WorkShop 6 Final Release

This document contains last minute information about Tools.h++ version 7.1.0. It describes the software corrections addressed by this release and lists the known problems, limitations, and incompatibilities. This readme describes version 7.1.0 of Tools.h++ as of September 1999, and as well as earlier versions (where indicated).

To view the text version of this document, type the following at a command prompt:

   example% more /opt/SUNWspro/READMEs/Tools.h++

To access the HTML version of this document, point your Netscape(TM) Communicator 4 or compatible Netscape version browser to:


Note - If your Sun WorkShop software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.

For more information, see:

  • Sun WorkShop 6 Release Notes -- Describes installation-related and late-breaking information about this final release. Information in the release notes overrides information in all readme files.

  • About Sun WorkShop 6 Documentation -- Describes the documentation available with this Sun WorkShop release and how to access it.

  • What's New in Sun WorkShop 6 -- Describes the new features in this release of Sun WorkShop.
These documents are accessible in HTML by pointing your browser to /opt/SUNWspro/docs/index.html. If your Sun WorkShop software is not installed in the /opt directory, ask your system administrator for the equivalent path on your system.


  1. Software Corrections and New Features 
  2. Problems and Workarounds 
  3. Limitations and Incompatibilities 
  4. Documentation Errata 
  5. Frequently Asked Questions 


A. Software Corrections and New Features

  1. New Static Function for Deducing Daylight Saving Rule: RWZone::os()

    A new static function, RWZone::os() has been added to zone.cpp. When envoked, this function will deduce the current daylight saving rule fron the underlying system. Instantiating RWZone::local( RWZone::os() ) will set the daylight rule for the current year.

  2. Fixed an RWXDRi(o)stream bug(7340): XDR stream supports 64-bit on IRIX.

  3. Fixed an RWTime bug(9194) in converting from time_t and back to RWTime.

  4. Fixed an RWCRExpr bug(11049): infinite loop in compiling an unterminated bracket list.

  5. Fixed a problem in RWCRExpr that will result in an invalid status if caret (^ is found not immediately following open bracket inside a bracket expression.

  6. Fixed a bug in RWCRExpr that does not match the longest pattern in a string.

  7. The removeFirst() method of templatized vectors now throws a Boundary Error if the index is invalid.

  8. Added operator== to RWT***OrderedVector and also operator< to RWT***SortedVector so that these classes can now be instantiated recursively without using the Standard C++ Library.


B. Problems and Workarounds

This section discusses the software bugs that could not be fixed in time for this release. For updated information, check Hot News for Sun WorkShop 6 (http://www.sun.com/workshop/users/ws.html).

  1. RWCString constructors are still significantly slower in the thread-ready version of the library. This should not affect most users.

  2. We have changed several member functions in the template collection classes to return const T& rather than T. This is generally a win because it means that the overhead of copying things from method to method is avoided. However, in a few cases, code will break: If your code depended on getting a copy of an object to avoid const issues, you may now find that your non-const methods will not work with our const references. The ideal solution is to re-write your code to be const correct.

  3. Problems persisting RWBoolean or bool using operators << and >> with vstreams. If your compiler supports bool as a "real type", we undef RW_NO_BOOL, and typedef RWBoolean to bool. But because converting a pointer to a bool is a standard conversion, if we had provided operators >> and << to extract or insert RWBoolean (bool) from and to vstreams, your compiler might correctly complain that it cannot choose between (for instance):
    (for instance)
           operator<<(RWVostream&, const RWCollectable*)
    when you attempt code like
           anRWpostream << aDerivedCollectable*
    (The reason it cannot decide is that in each case, one of the arguments is an exact match, but the other requires a built-in conversion, thus each choice is equally good.)

    This problem can be addressed by re-designing the Tools.h++ virtual streams, but the required change is neither link compatible (nor even code compatible for some users) with the current state of our code, so that solution will be postponed. For the moment, we have instead removed the insertion and extraction operators overloaded for bool. This restriction does not apply to the put() and get() methods of the vstream hierarchy, so RWBoolean (bool) may still be persisted, but not using the overloaded operators.

    Unfortunately, those compilers which trigger this problem will quietly convert a bool to some other type when inserting into a vstream: code such as this appears to work:

         aPostream << FALSE << " or " << TRUE;
    but the corresponding extractor will fail:
         aPistream >> oneRWBoolean << aString << anotherRWBoolean;
    Equally unfortunate, at least one of these compilers will issue a completely unhelpful diagnostic suggesting that oneRWBoolean and anotherRWBoolean be changed to "const int reference." If your compiler issues any diagnostic suggestive of a problem extracting a bool from a vistream, you must apply the following fix, not just to extraction code (flagged by the compiler) but also to insertion code, because otherwise the number of bytes inserted will not match the number which you get() from the stream. The fix is to replace code like this:
         aVostream << anyBoolean;
    with this instead:
         aVistream &t;> anyBoolean;
    with this instead:

    Note that these fixes must be made in the bodies of both rwSaveGuts and rwRestoreGuts for any of your classes which need it, and also in both the saveGuts and restoreGuts methods of any of your own classes which derive from RWCollectable.


C. Limitations and Incompatibilities 

Because Tools.h++ 7.1.0 is not fully link compatible with the version of Tools.h++ shipped with Sun WorkShop Compilers C++ versions prior to version 5.0, applications and libraries that would use Tools.h++ 7.1.0 should recompile all source modules before linking.


D. Documentation Errata 

  1. Do Not Use Internal Classes

    Some classes which were developed purely for internal use by Tools.h++ appear in the documented hierarchy, but not in the class reference section. This omission is deliberate, and implies that the undocumented classes may be changed, augmented, or removed in a later release without warning to users. You should not use such classes.

  2. RWFactory

    The example for using RWFactory in the Class Reference is in error.

    This code example is wrong:

           RWBag* b = (RWBag*)getRWFactory()->create(__RWBAG);
    This code example is correct:
           RWBag* b = (RWBag*)rwCreateFromFactory(__RWBAG);

  3. RWTPtrSlistIterator

    Class Reference for RWTPtrSlistIterator should tell the user that if the slist is modified, the iterator is no longer valid. This is generally true for all iterators.

  4. Values Stored in the Templatized Dictionary Containers

    Values stored in the templatized dictionary containers must be able to respond to operator==() and operator<(). This is necessary when the Standard C++ Library is being used as the implementation for these classes because the standard requires it, and when our own implementation is used because we wanted to be sure that containers with identical keys but distinct values were not considered the same. According to the Draft ANSII/ISO Standard, compilers should only require these operators if they are used. Unfortunately, we know of several compilers that do not meet this part of the draft standard.

  5. Wording About operator== Too Restrictive

    The manual talks about the semantics of the types that may instantiate the templatized collections by saying something like "Class K must have * well-defined equality semantics (K::operator==(const K&))." The example is too restrictive. We should be saying that the compiler must be able to unambiguously find an operator== that applies to two instances of K regardless of how the operator is implemented.


    RW_CENTURY_REQD will force asString with the "x" format to output 4 digit years. Since asString defaults to the "x" formatting option, 4 digit years will also be the default. This doesn't affect the other formatting options, which are handled by the operating system.

  7. RWLocaleSnapshot

    The following paragraph applies to RWLocaleSnapshot, but is not in the documentation:

    Note - The constructor for class RWLocaleSnapshot calls the function setlocale, which is not thread-safe. For safety in multithreaded applications, instances of RWLocaleSnapshot must be constructed only when it can be guaranteed that no other thread may be using locale-dependent functions. To guarantee this condition, construct all instances of RWLocaleSnapshot in the initial thread before starting any other thread.There is no new information at this time. 


E. Frequently Asked Questions
  1. How do I contact Rogue Wave Software?

    Please don't contact Rogue Wave for support of your Sun product. If you want information on other Rogue Wave products you can call:

    541-754-3010 or

  2. How do I get support for Tools.h++?

    Use Sun support as you would for any other Sun product. Sun has access to Rogue Wave for updates, consulting, fixes, and so on, but Sun fully supports Tools.h++.

  3. Is the Sun version different from the Rogue Wave version?

    The Sun and Rogue Wave versions of Tools.h++ are built from the same source base. Bug fixes are brought into the master sources. Each releases on a separate schedule, however, so released versions are likely to be a slightly different. In general, Rogue Wave releases more often, so they are usually (although not always) a bit ahead.

    Sun maintains link-compatibility across minor releases, and may hold back selected fixes if they must break link compatibility. Maintaining link compatibility means you can link your new Tools.h++ library with object files compiled for the old Tools.h++ library.)

  4. Can I get the latest Rogue Wave version from Sun?

    Usually no; only if that's what Sun ships anyway. Sufficiently important bug fixes are likely to be available from Sun.

  5. Where are the Tools.h++ header files?


    example% CC -H <file>.cc 
    to determine the location of the Tools.h++ header files in in your installation, where <file>.cc includes at least one Tools.h++ header file.

  6. Is there a shared library version of librwtool?

    Yes, there is a shared library version for Tools.h++ 7.

  7. Can I build libraries that use Tools.h++?

    It's all right to build an archive library that depends on Tools.h++ if your library is just used internally inside your project, for example to simplify build procedures. If you intend to ship your archive library to anyone, your customer needs to have access to Tools.h++ as well. Sun customers may redistribute librwtool.so.2, but not the header files that go with it. See <install-directory>/READMEs/runtime.libraries for details.

  8. How do I print RWCStrings in dbx

    In Sun WorkShop, the command interpreter for dbx is a Korn shell, so you can define new dbx commands that do specialized debugging functions. Printing strings is an often-wanted facility. The Tools.h++ manual chapter on compiling and debugging describes ways to print strings in dbx. Another way to print an RWCString is to define a new dbx command, such as:

    function dumpstr
      print (char*)($1.pref_+1)
    Then in dbx you can say:
    (dbx) dumpstr myString
    (char *) (myString.pref_+1) = 0x28d5c "Contents of myString"
    You can put the definition of dumpstr into your .dbxrc file.

  9. Additional details

    • The capacity of RWCString and RWWString may be changed by calling the clone member function: aString.clone(0) will adjust the capacity of aString to be exactly large enough, whereas calling aString.clone(aString.length()+someMore) will leave someMore extra bytes in the buffer.

    • All iterators: If the collection is modified directly or through the use of any iterator except the one in question, then that iterator is no longer guaranteed to be valid. Some collections may be altered "most of the time" without such side effects, which could lead you into a trap if you come to expect that iterators may be trusted after the collection is modified. Beware.

    • Some templatized containers have a method clearAndDestroy(), which is not protected against the possibility that the container holds more than one pointer to the same object. Do not call clearAndDestroy() unless you are sure your container holds no duplicates. (This warning does not apply to RWCollections.)

    • Some Tools.h++ methods are overloaded to take either a pointer or an integer type. RWTime constructors, for example, may be passed either a struct tm* or an unsigned long representing seconds since the "beginning of time." If you attempt to pass a zero to such methods, the compiler will correctly complain about ambiguity. This may be resolved by holding the zero value in the appropriate type, casting it, or using a construction such as "0ul" for a manifest constant.

    • Problems with incorrect RWTime construction from struct tm*: The system function localtime() returns a pointer to a static struct tm. Subsequent calls to localtime overwrite that struct. RWTime uses RWZone::local(), which is not created until needed. That creation also calls localtime(). If you experience difficulty related to calls to localtime(), make a call to RWZone::local() before you first call localtime().

    • RWLocale::asString(struct tm*, ..%U.., RWZone&= RWZone::local()) returns different values for week of the year, for years that begin on Sunday, depending on the platform. Although the standard is precise, many vendors disagree on it. Rogue Wave passes the vendor's result without examining it, so if you care about cross-platform results, do not use the %U format specifier.

    • Problems using RWFactory, or polymorphic persistence: Before the factory can create an RWCollectable, that collectable and its identifier must be registered. The easy way to do this is by creating at least one instance of the particular RWCollectable in the program.

      This problem may manifest in several ways. Usually you will see this message:

      "[NOCREATE] RWFactory: no create function for class with ID (something)"

      However, it is possible to get a core dump or GPF during a call to theFactory->create(someID) (This call is made while reading in persisted RWCollectables). This can happen with some compilers that do not create an instance of an object if you instantiate only a pointer to the object.

    • When creating your own RWCollectable, it is important to provide your class with all the methods that the RWCollectable methods use. In particular, you must provide a default constructor that can be used to create new "empty" instances for the persistence mechanism to "fill", and a copy constructor that may be used to clone copies of your object to a new location. You should also be careful to have related methods and operators be consistent with each other: If you have comparison operators defined for your class, they should give results that match the values returned by the method compareTo().

    • When to use RWCollectable::recursiveStoreSize() and when to use RWCollectable::binaryStoreSize(). Although the answer is simple, it does sometimes require a bit of thought: recursiveStoreSize() should be used at the _top_ level of an RWCollectable when you plan to use operator<<() or the undocumented recursiveSaveOn() method. On the other hand, binaryStoreSize() should be used when you are interested in working with a _part_ of the entire collection; when you plan to use saveGuts().

      Neither of these methods deals with streams; these methods are only of use for RWFile. If you need to find the size of an RWCollectable as saved to a virtual stream, use the class RWAuditStreamBuffer.

    • Use of mutexes prior to main suffers from the paired difficulty of knowing the order of static initialization (no general solution) and knowing which pre-main thread should initialize a given mutex. There are no known software solutions to this problem. Therefore do not use static initialization code to call any thread-hot functions.

    • Using templatized hash-based containers in your class. Many customers have asked how to add to their own classes a class member that requires a non-default constructor, such as the Tools.h++ hash based containers. The answer is a special syntax known as "member initialization." Suppose your class should have a hash dictionary member:
        class MyClass {
          // ...
          RWTValHashDictionary myDict; // no ctor args here!
      Member initialization looks like this: Where you provide the actual constructor body, you have to use a ":" followed by a comma-separated list of constructors for each member which requires non-default construction. This example extends the previous example.
         MyClass::MyClass() : myDict(theHashFunction) /* like this */
         { /* code for your constructor */ }
      Of course, you could instead use the member initialization syntax to write an inline constructor if that makes sense. What you cannot do is add the constructor arguments to the _declaration_ of the dictionary in the class declaration.


Copyright 2000 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, CA 94303, U.S.A. All rights reserved. 

Sun, Sun Microsystems, the Sun logo, docs.sun.com, and Solaris are trademarks, registered trademarks, or service marks of Sun Microsystems, Inc. in the U.S. and other countries.