From 17e7554f421ad5c7246e6b051118afb0b1662c65 Mon Sep 17 00:00:00 2001 From: Felix Natter Date: Tue, 26 Jun 2001 16:10:04 +0000 Subject: [PATCH] porting-howto.html: Fixed some errors. 2001-06-26 Felix Natter * docs/html/17_intro/porting-howto.html: Fixed some errors. From-SVN: r43582 --- libstdc++-v3/ChangeLog | 4 + .../docs/html/17_intro/porting-howto.html | 1519 +++++++++-------- 2 files changed, 801 insertions(+), 722 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 73d26c9cc50..d540fbff729 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2001-06-26 Felix Natter + + * docs/html/17_intro/porting-howto.html: Fixed some errors. + 2001-06-26 Benjamin Kosnik * include/bits/stl_iterator.h (istream_iterator::operator->): Fix diff --git a/libstdc++-v3/docs/html/17_intro/porting-howto.html b/libstdc++-v3/docs/html/17_intro/porting-howto.html index 54290b328c2..cb1160fbdad 100644 --- a/libstdc++-v3/docs/html/17_intro/porting-howto.html +++ b/libstdc++-v3/docs/html/17_intro/porting-howto.html @@ -1,726 +1,801 @@ + - - Libstdc++-porting-howto - - - -
-
-

- Libstdc++-porting-howto -

-

Felix Natter

-

- 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. -
Revision 0.9Wed Sep 6 02:59:32 2000fnatter
5 new sections.
-
-
-

- 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 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". + + +Libstdc++-porting-howto + + +

+
+

+Libstdc++-porting-howto

+

Felix Natter

+
+

Legal Notice

+

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

+
+

Tue Jun 5 20:07:49 2001

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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. +
Revision 0.9Wed Sep 6 02:59:32 2000fnatter
5 new sections.
Revision 0.9.1Sat Sep 23 14:20:15 2000fnatter
added information about why file-descriptors are not in the + standard
Revision 0.9.2Tue Jun 5 20:07:49 2001fnatter
+ a fix, added hint on increased portability of C-shadow-headers, + added autoconf-test HAVE_CONTAINER_AT +
+
+

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

-
-
-
-

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

-

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

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

+
+
+
+ +

+ +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 author 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 +

+

+ Phil Edwards <pedwards@disaster.jaj.com> writes: + It was considered and rejected. Not all environments use file + descriptors. Of those that do, not all of them use integers to represent + them. +

+

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

+

+ +

+	  #include <fstream>
+	
+

+int basic_filebuf +(__fd, __name, __mode);
int __fd;
const char* __name;
ios_base::openmode __mode;

+

+

+ but the the signature of this constructor has changed often, and + it might change again. + For a portable solution (among systems which use + filedescriptors), you need to implement a subclass of + streambuf (or + basic_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. +

+

+ The old C++-headers (iostream.h etc.) are available, but gcc generates + a warning that you are using deprecated headers. +

+
+ +

+ +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, + omitting the extension (.h). For example, instead of using + <math.h>, you + should use <cmath>. In some cases this has + the advantage that the C++-header is more standardized than + the C-header (i.e. <ctime> (almost) + corresponds to either <time.h> or <sys/time.h>). - [ 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. - State of streams - -

-

- At least some older implementations don't have - std::ios_base, so you should use - std::ios::badbit, std::ios::failbit - and std::ios::eofbit and - std::ios::goodbit. -

-
-
-

- 8. vector::at is missing (i.e. gcc 2.95.2) -

-

- For my use, I added it to - prefix/include/g++-3/stl_vector.h: -

-  reference operator[](size_type __n) { return *(begin() + __n); }
-  reference at(size_type __n) {
-    if (begin() + __n >= end())
-      throw out_of_range("vector::at");
-    return *(begin() + __n);
-  }
-  const_reference operator[](size_type __n) const { return *(begin() + __n); }
-  const_reference at(size_type __n) const {
-    if (begin() + __n >= end())
-      throw out_of_range("vector::at");
-    return *(begin() + __n);
-  }
-	  
-

-
-
-

- 9. Using std::char_traits<char>::eof() -

-

-

-		#ifdef HAVE_CHAR_TRAITS
-		#define CPP_EOF std::char_traits<char>::eof()
-		#else
-		#define CPP_EOF EOF
-		#endif
-	  
-

-
-
-

- 10. Using string::clear()/string::erase() -

-

- There are two functions for deleting the contents of a string: - clear and erase (the latter - returns the string). -

-		void 
-		clear() { _M_mutate(0, this->size(), 0); }
-	  
-
-      basic_string& 
-      erase(size_type __pos = 0, size_type __n = npos)
-      { 
-		return this->replace(_M_check(__pos), _M_fold(__pos, __n),
-			     _M_data(), _M_data()); 
-      }
-	  
- The implementation of erase seems to be more - complicated (from libstdc++-v3), but clear is not - implemented in gcc 2.95.2's libstdc++, so you should use - erase (which is probably faster than - operator=(charT*)). -

-
-
-

- 11. Using stringstream's -

-

- Libstdc++-v3 includes the new - i/ostringstream-classes, (<sstream>), but with older - implementations you still have to use i/ostrstream - (<strstream>): -

-		#ifdef HAVE_SSTREAM
-		#include <sstream>
-		#else
-		#include <strstream>
-		#endif
-	  
-
-
    -
  • - -

    strstream is considered to be - deprecated -

    -
  • -
  • - -

    strstream is limited to - char -

    -
  • -
  • - -

    with ostringstream you don't - have to take care of terminating the string or freeing its - memory -

    -
  • -
  • - -

    istringstream can be re-filled - (clear(); str(input);) -

    -
  • -
-
-

-

- You can then use output-stringstreams like this: -

-		#ifdef HAVE_SSTREAM
-		std::ostringstream oss;
-		#else
-		std::ostrstream oss;
-		#endif
-		oss << "Name=" << m_name << ", number=" << m_number << std::endl;
-		...
-		#ifndef HAVE_SSTREAM
-		oss << std::ends; // terminate the char*-string
-		#endif
-		// str() returns char* for ostrstream and a string for ostringstream
-		// this also causes ostrstream to think that the buffer's memory
-		// is yours
-		m_label.set_text(oss.str());
-		#ifndef HAVE_SSTREAM
-		// let the ostrstream take care of freeing the memory
-		oss.freeze(false);
-		#endif
-	  
-

-

- Input-stringstreams can be used similarly: -

-		std::string input;
-		...
-		#ifdef HAVE_SSTREAM
-		std::istringstream iss(input);
-		#else
-		std::istrstream iss(input.c_str());
-		#endif
-		int i;
-		iss >> i; 
-	  
- One (the only?) restriction is that an istrstream cannot be re-filled: -
-		std::istringstream iss(numerator);
-		iss >> m_num;
-		// this is not possible with istrstream
-		iss.clear();
-		iss.str(denominator);
-		iss >> m_den;
-	  
- If you don't care about speed, you can put these conversions in - a template-function: -
-		template <class X>
-		void fromString(const string& input, X& any)
-		{
-		#ifdef HAVE_SSTREAM
-		std::istringstream iss(input);
-		#else
-		std::istrstream iss(input.c_str());
-		#endif
-		X temp;
-		iss >> temp;
-		if (iss.fail())
-		   throw runtime_error(..)
-		any = temp;
-		}
-	  
-

-

- I have read the Josuttis book on Standard C++, so some information - comes from there. Additionally, there is information in - "info iostream", which covers the old implementation that gcc 2.95.2 - uses. -

-
-
-

- 12. About... -

-

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

-
-
- + 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:: (but + libstdc++ does not yet have fully compliant headers) 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 might reuse ("shadow") the C + library-functions, have a look at + www.cantrip.org. +

+
+
+ +

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

+

+ In earlier 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 . +

+

+ Older implementations of libstdc++ (g++-2 for egcs 1.x and g++-3 + for gcc 2.95.x), 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.x) 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
+
+	[ 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. + State of streams + +

+

+ At least some older implementations don't have + std::ios_base, so you should use + std::ios::badbit, std::ios::failbit + and std::ios::eofbit and + std::ios::goodbit. +

+
+
+ +

+ +8. vector::at is missing (i.e. gcc 2.95.x) +

+

+ You could easily modify the header-files: + prefix/include/g++-3/stl_vector.h: +

+	reference operator[](size_type __n) { return *(begin() + __n); }
+	reference at(size_type __n) {
+	if (begin() + __n >= end())
+	throw out_of_range("vector::at");
+	return *(begin() + __n);
+	}
+	const_reference operator[](size_type __n) const { return *(begin() + __n); }
+	const_reference at(size_type __n) const {
+	if (begin() + __n >= end())
+	throw out_of_range("vector::at");
+	return *(begin() + __n);
+	}
+      
+ (and so on for deque and string) + + Of course a better solution is to add an autoconf-test for this: +
+	AC_MSG_CHECKING(for container::at)
+	AC_TRY_COMPILE(
+	[
+	#include <vector>
+	#include <deque>
+	#include <string>
+	
+	using namespace std;
+	],
+	[
+	deque<int> test_deque(3);
+	test_deque.at(2);
+	vector<int> test_vector(2);
+	test_vector.at(1);
+	string test_string("test_string");
+	test_string.at(3);
+	],
+	[AC_MSG_RESULT(yes)
+	AC_DEFINE(HAVE_CONTAINER_AT)],
+	[AC_MSG_RESULT(no)])
+      
+ If you are using other (non-GNU) compilers it might be a good idea + to check for string::at separately. +

+
+
+ +

+ +9. Using std::char_traits<char>::eof() +

+

+

+	#ifdef HAVE_CHAR_TRAITS
+	#define CPP_EOF std::char_traits<char>::eof()
+	#else
+	#define CPP_EOF EOF
+	#endif
+      
+

+
+
+ +

+ +10. Using string::clear()/string::erase() +

+

+ There are two functions for deleting the contents of a string: + clear and erase (the latter + returns the string). +

+	void 
+	clear() { _M_mutate(0, this->size(), 0); }
+      
+
+	basic_string& 
+	erase(size_type __pos = 0, size_type __n = npos)
+	{ 
+	return this->replace(_M_check(__pos), _M_fold(__pos, __n),
+	_M_data(), _M_data()); 
+	}
+      
+ The implementation of erase seems to be more + complicated (from libstdc++-v3), but clear is not + implemented in gcc 2.95.x's libstdc++, so you should use + erase (which is probably faster than + operator=(charT*)). +

+
+
+ +

+ +11. Using stringstream's +

+

+ Libstdc++-v3 provides the new + i/ostringstream-classes, + (<sstream>), but with older + implementations you still have to use i/ostrstream + (<strstream>): +

+	#ifdef HAVE_SSTREAM
+	#include <sstream>
+	#else
+	#include <strstream>
+	#endif
+      
+
    +
  • + strstream is considered to be + deprecated +

  • +
  • + strstream is limited to + char +

  • +
  • + with ostringstream you don't + have to take care of terminating the string or freeing its + memory +

  • +
  • + istringstream can be re-filled + (clear(); str(input);) +

  • +
+

+

+ You can then use output-stringstreams like this: +

+	#ifdef HAVE_SSTREAM
+	std::ostringstream oss;
+	#else
+	std::ostrstream oss;
+	#endif
+	oss << "Name=" << m_name << ", number=" << m_number << std::endl;
+	...
+	#ifndef HAVE_SSTREAM
+	oss << std::ends; // terminate the char*-string
+	#endif
+	// str() returns char* for ostrstream and a string for ostringstream
+	// this also causes ostrstream to think that the buffer's memory
+	// is yours
+	m_label.set_text(oss.str());
+	#ifndef HAVE_SSTREAM
+	// let the ostrstream take care of freeing the memory
+	oss.freeze(false);
+	#endif
+      
+

+

+ Input-stringstreams can be used similarly: +

+	std::string input;
+	...
+	#ifdef HAVE_SSTREAM
+	std::istringstream iss(input);
+	#else
+	std::istrstream iss(input.c_str());
+	#endif
+	int i;
+	iss >> i; 
+      
+ One (the only?) restriction is that an istrstream cannot be re-filled: +
+	std::istringstream iss(numerator);
+	iss >> m_num;
+	// this is not possible with istrstream
+	iss.clear();
+	iss.str(denominator);
+	iss >> m_den;
+      
+ If you don't care about speed, you can put these conversions in + a template-function: +
+	template <class X>
+	void fromString(const string& input, X& any)
+	{
+	#ifdef HAVE_SSTREAM
+	std::istringstream iss(input);
+	#else
+	std::istrstream iss(input.c_str());
+	#endif
+	X temp;
+	iss >> temp;
+	if (iss.fail())
+	throw runtime_error(..)
+	any = temp;
+	}
+      
+

+

+ I have read the Josuttis book on Standard C++, so some information + comes from there. Additionally, there is information in + "info iostream", which covers the old implementation that gcc 2.95.x + uses. +

+
+
+ +

+ +12. About... +

+

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

+
+ -- 2.30.2