Porting to libstdc++-v3

  • Namespaces std
  • File-flags: ios::nocreate and ios::noreplace
  • The new headers
  • Comments, suggestions, corrections, questions...
  • Namespace std::

    The latest C++-standard (ISO-14882) requires that the standard C++-library is defined in namespace std::. Thus, to use classes from the standard c++ library, you can do one of three things:

    Namespace portability-issues are not a problem with g++, because versions of g++ that do not have libstdc++ in std:: use -fno-honor-std (ignore std::, :: = std::) by default. This probably applies to some other compilers as well. The following sections list some possible solutions to support compilers that cannot ignore std::.

    Using namespace composition if the project uses a separate namespace

    Gtk-- defines most of its classes in namespace Gtk::. Thus, it was possible to adapt Gtk-- to namespace std:: by using a C++-feature called namespace composition. This is what happens if you put a using-declaration into a namespace-definition: the imported symbol(s) gets imported into the currently active namespace(s). This is what it looks like in Gtk--:

    namespace Gtk {
    	using std::string;
    	class Window { ... }
    }
    
    In this example, std::string gets imported into namespace Gtk::. The result is that you don't have to use std::string in this header, but still std::string does not get imported into user-space (the global namespace ::) unless the user does using namespace Gtk; (which is not recommended practice for Gtk--, so it is not a problem).

    Defining an empty namespace std for backwards-compatibility

    By defining an (empty) namespace std:: before using it, you can avoid getting errors on systems where no part of the library is in std:

    namespace std { }
    using namespace std;
    

    Avoid to use fully qualified names (i.e. std::string)

    If some compilers complain about using std::string;, and if the hack for gtk-- mentioned above does not work, then it might be a good idea to define a macro NS_STD, which is defined to either "" or "std" based on an autoconf-test. Then you should be able to use NS_STD::string, which will evaluate to ::string ("string in the global namespace") on systems that do not put string in std::. (This is untested and might not even be necessary)

    How some open-source-projects deal with this

    clanlib usual
    pingus usual
    mozilla usual
    mnemonic none
    libsigc++ portable-impl
    Notations for categories
    usual mostly fully qualified names and some using-declarations (but not in headers)
    none no namespace std at all
    portable-impl wrap all namespace-handling in macros to support compilers without namespace-support (no libstdc++ used in headers)

    there is no ios::nocreate/ios::noreplace in ISO 14882

    I have seen ios::nocreate being used for input-streams, most probably because the authors thought it would be more correct to specify nocreate "explicitly". So you can simply leave it out for input-streams.

    For output streams, "nocreate" is probably the default, unless you specify std::ios::trunc ? To be safe, you can open the file for reading, check if it has been opened, and then decide whether you want to create/replace or not.

    stream::attach(int fd) is not in the standard any more

    With libstdc++-v3, you can use

    basic_filebuf(int __fd, const char*__name, ios_base::openmode __mode)
    
    For a portable solution (if there is one), you need to implement a subclass of streambuf which opens a file given a descriptor, and then pass an instance of this to the stream-constructor (from the Josuttis-book).

    The new headers

    The new headers can be seen in this source file.

    I think it is a problem for libstdc++-v3 to add links or wrappers for the old headers, because the implementation has changed, and the header-name-changes indicate this. It might be preferable to use the new headers and tell users of old compilers that they should create links (which is what they will have to do sometime anyway).

    <ctype.h> introduces ambiguity when used with <cctype>

    The best solution I came up with so far is to include cctype instead of ctype.h wherever possible, and then use fully qualified names to refer to the libstdc++-versions: std::islower, std::isalnum etc. (you will need to as soon as any header includes <ctype.h>, because then there will be an ambiguity with the C-versions in the global namespace defined in <ctype.h>)

    <fstream> does not define std::cout, std::cin etc.

    In previous versions of the standard, <fstream.h>, <ostream.h> and <istream.h> used to define cout, cin and so on. With libstdc++-v3, you need to include <iostream> to define these.

    About...

    Please send any experience, additions, corrections or questions to fnatter@gmx.net or for discussion to the libstdc++-v3-mailing-list.