From 320f95489d1a822d0b67fa63aa5691d70cd3ae0d Mon Sep 17 00:00:00 2001 From: Felix Natter Date: Mon, 7 Aug 2000 19:29:19 +0000 Subject: [PATCH] porting-howto.html: New version. 2000-08-07 Felix Natter * docs/17_intro/porting-howto.html: New version. From-SVN: r35555 --- libstdc++-v3/ChangeLog | 4 + libstdc++-v3/docs/17_intro/porting-howto.html | 799 ++++++++++++++++---------- 2 files changed, 508 insertions(+), 295 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 427d3cc..df0e50a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2000-08-07 Felix Natter + + * docs/17_intro/porting-howto.html: New version. + 2000-08-03 Mark Mitchell * bits/locale_facets.h (ctype::ctype): Don't name unused diff --git a/libstdc++-v3/docs/17_intro/porting-howto.html b/libstdc++-v3/docs/17_intro/porting-howto.html index 4d4c254..4e6422e 100644 --- a/libstdc++-v3/docs/17_intro/porting-howto.html +++ b/libstdc++-v3/docs/17_intro/porting-howto.html @@ -1,305 +1,514 @@ - - - Libstdc++-porting-howto + - - - -

Porting to libstdc++-v3

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

    -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". -

    - - -

    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: -

      -
    • wrap your code in namespace std { ... } => This is not an - option because only symbols from the standard c++-library are defined in - namespace std::. - -
    • put a kind of using-declaration in your source (either - using namespace std; or i.e. using std::string;) - => works well for source-files, but cannot be used in header-files - -
    • use a fully qualified name for each libstdc++-symbol - (i.e. std::string, std::cout) => can always be used -
    -

    -

    -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::. -

    - -

    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). 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 ) -

    - -

    Defining an empty namespace std

    -

    -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;
    -
    -

    -

    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) -

    - -

    How some open-source-projects deal with this

    -

    - - - - - - - - - - - - - -
    clanlib usual
    pingus usual
    mozilla usual
    mnemonic none
    libsigc++conservative-impl
    - - - - - - - - - - - - -
    Notations for categories
    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)
    -As you can see, this currently lacks an example of a project which uses -libstdc++-symbols in headers in a back-portable way -(except for the Gtk-- "hack"). -

    - -

    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. To my knowledge, even older implementations support -app, ate and trunc (except for app ?). -

    - -

    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). -

    - - -

    New headers replacing C-headers

    -
    -

    -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). -

    + +
    +
    +

    + Libstdc++-porting-howto +

    +

    Felix Natter

    -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. -

    - -

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

    + This document can be distributed under the FDL + (www.gnu.org) +

    +

    what kind of a date ? I don't drink !

    +
    + + + + + + + + + + + + + + + + +
    Revision History
    Revision 0.5Thu Jun 1 13:06:50 2000fnatter
    First docbook-version.
    Revision 0.8Sun Jul 30 20:28:40 2000fnatter
    First released version using docbook-xml + + second upload to libstdc++-page. +
    +
    +
    +

    + Abstract +

    +

    + Some notes on porting applications from libstdc++-2.90 (or earlier + versions) to libstdc++-v3. Not speaking in terms of the GNU libstdc++ + implementations, this means porting from earlier versions of the + C++-Standard to ISO 14882. +

    +
    +
    +
    +

    -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. -

    - - -

    Iterators

    -
    -

    -The following are not proper uses of iterators, but may be working fixes -for existing uses of iterators. -

      -
    • you cannot do ostream::operator<<(iterator) to print the - address of the iterator => use << &*iterator instead ? -
    • you cannot clear an iterator's reference (iterator = 0) - => use iterator = iterator_type(); ? -
    • if (iterator) won't work any more - => use if (iterator != iterator_type()) ? -
    -

    - - -

    Libc-macros (i.e. isspace from <cctype>)

    -
    -

    -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. -

    + Table of Contents +

    +
    +
    1. Namespace std:: +
    +
    +
    +
    1.1.1. Using namespace + composition if the project uses a separate + namespace +
    +
    1.1.2. Defining an empty namespace std +
    +
    1.1.3. Avoid to use fully qualified names + (i.e. std::string) +
    +
    1.1.4. How some open-source-projects deal + with this +
    +
    +
    +
    2. there is no ios::nocreate/ios::noreplace + in ISO 14882 +
    +
    3. stream::attach(int + fd) is not in the standard any more +
    +
    4. The new headers +
    +
    +
    +
    4.4.1. New headers replacing C-headers +
    +
    4.4.2. + <fstream> does + not define std::cout, + std::cin etc. +
    +
    +
    +
    5. Iterators +
    +
    6. + Libc-macros (i.e. isspace from + <cctype>) +
    +
    7. About... +
    +
    +

    -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> ]
    -
    -

    + 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". +

    +
    +

    + 1. Namespace std:: +

    +

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

    +
      +
    • + +

      wrap your code in namespace std { + ... } => This is not an option because only symbols + from the standard c++-library are defined in namespace std::. +

      +
    • +
    • + +

      put a kind of + using-declaration in your source (either + using namespace std; or i.e. using + std::string;) => works well for source-files, but + cannot be used in header-files. +

      +
    • +
    • + +

      use a fully qualified name for + each libstdc++-symbol (i.e. std::string, + std::cout) => can always be used +

      +
    • +
    +
    +

    +

    + 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::. +

    +
    +

    + 1.1.1. 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). 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 + <kenelson@ece.ucdavis.edu>) +

    +
    +
    +

    + 1.1.2. Defining an empty namespace std +

    +

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

    +		  namespace std { }
    +		  using namespace std;
    +		
    +

    +
    +
    +

    + 1.1.3. 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) +

    +
    +
    +

    + 1.1.4. How some open-source-projects deal + with this +

    +

    + This information was gathered around May 2000. It may not be correct + by the time you read this. +

    +
    +

    + Table 1. Namespace std:: in Open-Source programs +

    + + + + + + + + + + + + + + + + + + + + + + +
    clanlibusual
    pingususual
    mozillausual
    mnemonicnone
    + libsigc++conservative-impl
    +
    +
    +

    + Table 2. Notations for categories +

    + + + + + + + + + + + + + + + + +
    usualmostly fully qualified names and some + using-declarations (but not in headers)
    noneno namespace std at all
    conservative-implwrap all + namespace-handling in macros to support compilers without + namespace-support (no libstdc++ used in headers)
    +
    +

    + As you can see, this currently lacks an example of a project which + uses libstdc++-symbols in headers in a back-portable way (except + for Gtk--: see the section on the Gtk-- hack + ). +

    +
    +
    +
    +

    + 2. 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. To my knowledge, even + older implementations support app, + ate and trunc (except for + app ?). +

    +
    +
    +

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

    +

    + When using libstdc++-v3, you can use +

    +

    +

    + +
    +		  #include <fstream>
    +		
    +

    + int basic_filebuf(__fd, __name, __mode);
    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). +

    +
    +
    +

    + 4. The new headers +

    +

    + All new headers can be seen in this source-code. +

    +

    + 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). +

    +
    +

    + 4.4.1. New headers replacing C-headers +

    +

    + 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. <pcmath>), 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. +

    +
    +
    +

    + 4.4.2. + <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. Because + of the templatized iostreams in libstdc++-v3, you need to include + <iostream> + explicitly to define these. +

    +
    +
    +
    +

    + 5. Iterators +

    +

    + The following are not proper uses of iterators, but may be working + fixes for existing uses of iterators. +

    +
      +
    • + +

      you cannot do + ostream::operator<<(iterator) to + print the address of the iterator => use + operator<< &*iterator instead ? +

      +
    • +
    • + +

      you cannot clear an iterator's reference + (iterator = 0) => use + iterator = iterator_type(); ? +

      +
    • +
    • + +

      + if (iterator) won't work any + more => use if (iterator != iterator_type()) + ?

      +
    • +
    +
    +

    +
    +
    +

    + 6. + Libc-macros (i.e. isspace from + <cctype>) +

    +

    + 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 )  ;
    +	  
    +

    +

    + 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) define a + macro which tells <ctype.h> to define functions + instead of macros: +

    +		// This keeps isalnum, et al from being propagated as macros.
    +		#if __linux__
    +		#define __NO_CTYPE 1
    +		#endif
     
    -    
    -	

    About...

    -
    -

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

    - + [ now include <ctype.h> ] +
    +

    +

    + 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>). +

    +

    + The solution to this problem was posted to the libstdc++-v3 + mailing-list: + Benjamin Kosnik <bkoz@redhat.com> writes: + " + --enable-cshadow-headers is currently broken. As a result, shadow + headers are not being searched.... + " +

    +
    +
    +

    + 7. About... +

    +

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

    +
    +
    - -- 2.7.4