In the following, when I say portable, I will refer to "portable among ISO 14882-implementations". On the other hand, if I say "backportable" or "conservative", I am talking about "compiles with older libstdc++-implementations".
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:
Because there are many compilers which still use an implementation that does not have the standard C++-library in namespace std::, some care is required to support these as well.
Namespace back-portability-issues are generally 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. That is, the responsibility for enabling or disabling std:: is on the user; the maintainer does not have to care about it. This probably applies to some other compilers as well.
The following sections list some possible solutions to support compilers that cannot ignore std::.
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). For example:
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). Additionally, the using-declarations are wrapped in macros that are set based on autoconf-tests to either "" or i.e. using std::string; (depending on whether the system has libstdc++ in std:: or not). (ideas from llewelly@dbritsch.dsl.xmission.com, Karl Nelson
By defining an (empty) namespace std:: before using it, you can avoid getting errors on systems where no part of the library is in namespace std:
namespace std { } using namespace std;
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)
clanlib | usual |
pingus | usual |
mozilla | usual |
mnemonic | none |
libsigc++ | conservative-impl |
usual | mostly fully qualified names and some using-declarations (but not in headers) |
none | no namespace std at all |
conservative-impl | wrap all namespace-handling in macros to support compilers without namespace-support (no libstdc++ used in headers) |
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. To my knowledge, even older implementations support app, ate and trunc (except for app ?).
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 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).
You should not use the C-headers (except for system-level headers) from C++ programs. Instead, you should use a set of headers that are named by prepending 'c' and, as usual, ommiting the extension (.h). For example, instead of using <math.h>, you should use <cmath>. The standard specifies that if you include the C-style header (<math.h> in this case), the symbols will be available both in the global namespace and in namespace std:: (libstdc++-v3, version 2.90.8 currently puts them in std:: only) On the other hand, if you include only the new header (i.e. <cmath>), the symbols will only be defined in namespace std:: (and macros will be converted to inline-functions).
For more information on this, and for information on how the GNU C++ implementation reuses ("shadows") the C library-functions, have a look at www.cantrip.org.
In previous versions of the standard, <fstream.h>, <ostream.h> and <istream.h> used to define cout, cin and so on. Because of the templatized iostreams in libstdc++-v3, you need to include <iostream> explicitly to define these.
The following are not proper uses of iterators, but may be working fixes for existing uses of iterators.
Glibc 2.0.x and 2.1.x define the <ctype.h>-functionality as macros (isspace, isalpha etc.). Libstdc++-v3 "shadows" these macros as described in the section on C-headers.
Older implementations of libstdc++ (g++-2 for egcs 1.x and g++-3 for gcc 2.95.2), however, keep these functions as macros, and so it is not back-portable to use fully qualified names. For example:
#include <cctype> int main() { std::isspace('X'); }will result in something like this (unless using g++-v3):
std:: (__ctype_b[(int) ( ( 'X' ) )] & (unsigned short int) _ISspace ) ;Another problem arises if you put a using namespace std; declaration at the top, and include <ctype.h>. This will result in ambiguities between the definitions in the global namespace (<ctype.h>) and the definitions in namespace std:: (<cctype>).
One solution I can think of is to test for -v3 using autoconf-macros, and define macros for each of the C-functions (maybe that is possible with one "wrapper" macro as well ?).
Another solution which would fix g++ is to tell the user to modify a header-file so that g++-2 (egcs 1.x) and g++-3 (gcc 2.95.2) enable a macro which tells <ctype.h> to define functions instead of macros:
// This keeps isanum, et al from being propagated as macros. #if __linux__ #define __NO_CTYPE 1 #endif [ now include <ctype.h> ]
Please send any experience, additions, corrections or questions to fnatter@gmx.net or for discussion to the libstdc++-v3-mailing-list.