| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
| <html> |
| <head> |
| <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"> |
| <title>Libstdc++-porting-howto</title> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.48"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article"> |
| <div class="titlepage"> |
| <div><h1 class="title"> |
| <a name="libstdc++-porting-howto"></a>Libstdc++-porting-howto</h1></div> |
| <div><h3 class="author">Felix Natter</h3></div> |
| <div><div class="legalnotice"> |
| <p class="legalnotice-title"><b>Legal Notice</b></p> |
| <p> |
| This document can be distributed under the FDL |
| (<a href="http://www.gnu.org" target="_top">www.gnu.org</a>) |
| </p> |
| </div></div> |
| <div><p class="pubdate">Tue Jun 5 20:07:49 2001</p></div> |
| <div><div class="revhistory"><table border="1" width="100%" summary="Revision history"> |
| <tr><th align="left" valign="top" colspan="3"><b>Revision History</b></th></tr> |
| <tr> |
| <td align="left">Revision 0.5</td> |
| <td align="left">Thu Jun 1 13:06:50 2000</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3">First docbook-version.</td></tr> |
| <tr> |
| <td align="left">Revision 0.8</td> |
| <td align="left">Sun Jul 30 20:28:40 2000</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3">First released version using docbook-xml |
| + second upload to libstdc++-page. |
| </td></tr> |
| <tr> |
| <td align="left">Revision 0.9</td> |
| <td align="left">Wed Sep 6 02:59:32 2000</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3">5 new sections.</td></tr> |
| <tr> |
| <td align="left">Revision 0.9.1</td> |
| <td align="left">Sat Sep 23 14:20:15 2000</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3">added information about why file-descriptors are not in the |
| standard</td></tr> |
| <tr> |
| <td align="left">Revision 0.9.2</td> |
| <td align="left">Tue Jun 5 20:07:49 2001</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3"> |
| a fix, added hint on increased portability of C-shadow-headers, |
| added autoconf-test HAVE_CONTAINER_AT |
| </td></tr> |
| <tr> |
| <td align="left">Revision 0.9.3</td> |
| <td align="left">Fri Jun 29 16:15:56 2001</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3"> |
| changed signature of nonstandard filebuf-constructor and |
| update the section on filebuf::attach to point to ../ext/howto.html, |
| added link to ../21/strings/howto.html |
| in sec-stringstream, changed <link>-tags to have content |
| (so that these links work), |
| replace "user-space" by "global namespace" |
| add note about gcc 3.0 and shadow-headers |
| add section about ostream::form and istream::scan |
| sec-vector-at: remove hint to modify headers |
| fix spelling error in sec-stringstream |
| </td></tr> |
| <tr> |
| <td align="left">Revision 0.9.4</td> |
| <td align="left">Mon Nov 5 17:01:04 2001</td> |
| <td align="left">fnatter</td> |
| </tr> |
| <tr><td align="left" colspan="3"> |
| rewrite section 1.1.3 because of gnu.gcc.help-post by |
| Juergen Heinzl |
| </td></tr> |
| </table></div></div> |
| <div><div class="abstract"> |
| <p><b>Abstract</b></p> |
| <p> |
| 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. |
| </p> |
| </div></div> |
| <hr> |
| </div> |
| <div class="toc"> |
| <p><b>Table of Contents</b></p> |
| <dl> |
| <dt>1. <a href="#sec-nsstd">Namespace std::</a> |
| </dt> |
| <dd><dl> |
| <dt>1.1.1. <a href="#sec-gtkmm-hack">Using namespace |
| composition if the project uses a separate |
| namespace</a> |
| </dt> |
| <dt>1.1.2. <a href="#sec-emptyns">Defining an empty namespace std</a> |
| </dt> |
| <dt>1.1.3. <a href="#sec-avoidfqn">Avoid to use fully qualified names |
| (i.e. std::string)</a> |
| </dt> |
| <dt>1.1.4. <a href="#sec-osprojects">How some open-source-projects deal |
| with this</a> |
| </dt> |
| </dl></dd> |
| <dt>2. <a href="#sec-nocreate">there is no ios::nocreate/ios::noreplace |
| in ISO 14882</a> |
| </dt> |
| <dt>3. <a href="#sec-stream::attach">stream::attach(int |
| fd) is not in the standard any more</a> |
| </dt> |
| <dt>4. <a href="#sec-headers">The new headers</a> |
| </dt> |
| <dd><dl> |
| <dt>4.4.1. <a href="#sec-cheaders">New headers replacing C-headers</a> |
| </dt> |
| <dt>4.4.2. <a href="#sec-fstream-header"> |
| <fstream> does |
| not define std::cout, |
| std::cin etc.</a> |
| </dt> |
| </dl></dd> |
| <dt>5. <a href="#sec-iterators">Iterators</a> |
| </dt> |
| <dt>6. <a href="#sec-macros"> |
| Libc-macros (i.e. isspace from |
| <cctype>)</a> |
| </dt> |
| <dt>7. <a href="#sec-stream-state">State of streams</a> |
| </dt> |
| <dt>8. <a href="#sec-vector-at">vector::at is missing (i.e. gcc 2.95.x)</a> |
| </dt> |
| <dt>9. <a href="#sec-eof">Using std::char_traits<char>::eof()</a> |
| </dt> |
| <dt>10. <a href="#sec-string-clear">Using string::clear()/string::erase()</a> |
| </dt> |
| <dt>11. <a href="#sec-scan-form">GNU Extensions ostream::form and istream::scan</a> |
| </dt> |
| <dt>12. <a href="#sec-stringstream">Using stringstreams</a> |
| </dt> |
| <dt>13. <a href="#sec-about">About...</a> |
| </dt> |
| </dl> |
| </div> |
| <p> |
| 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". |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-nsstd"></a>Namespace std::</h2></div></div> |
| <p> |
| 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: |
| <div class="itemizedlist"><ul type="disc"> |
| <li><p>wrap your code in <b>namespace std { |
| ... }</b> => This is not an option because only symbols |
| from the standard c++-library are defined in namespace std::. |
| </p></li> |
| <li><p>put a kind of |
| <span class="emphasis"><i>using-declaration</i></span> in your source (either |
| <b>using namespace std;</b> or i.e. <b>using |
| std::string;</b>) => works well for source-files, but |
| cannot be used in header-files. |
| </p></li> |
| <li><p>use a <span class="emphasis"><i>fully qualified name</i></span> for |
| each libstdc++-symbol (i.e. <b>std::string</b>, |
| <b>std::cout</b>) => can always be used |
| </p></li> |
| </ul></div> |
| </p> |
| <p> |
| Because there are many compilers which still use an implementation |
| that does not have the standard C++-library in namespace |
| <b>std::</b>, some care is required to support these as |
| well. |
| </p> |
| <p> |
| Namespace back-portability-issues are generally not a problem with |
| g++, because versions of g++ that do not have libstdc++ in |
| <b>std::</b> use <b>-fno-honor-std</b> |
| (ignore <b>std::</b>, <b>:: = std::</b>) by |
| default. That is, the responsibility for enabling or disabling |
| <b>std::</b> is on the user; the maintainer does not have |
| to care about it. This probably applies to some other compilers as |
| well. |
| </p> |
| <p> |
| The following sections list some possible solutions to support compilers |
| that cannot ignore std::. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-gtkmm-hack"></a>Using <span class="emphasis"><i>namespace |
| composition</i></span> if the project uses a separate |
| namespace</h3></div></div> |
| <p> |
| <a href="http://gtkmm.sourceforge.net" target="_top">Gtk--</a> defines |
| most of its classes in namespace Gtk::. Thus, it was possible to |
| adapt Gtk-- to namespace std:: by using a C++-feature called |
| <span class="emphasis"><i>namespace composition</i></span>. This is what happens if |
| you put a <span class="emphasis"><i>using</i></span>-declaration into a |
| namespace-definition: the imported symbol(s) gets imported into the |
| currently active namespace(s). For example: |
| <pre class="programlisting"> |
| namespace Gtk { |
| using std::string; |
| class Window { ... } |
| } |
| </pre> |
| In this example, <b>std::string</b> gets imported into |
| namespace Gtk::. The result is that you don't have to use |
| <b>std::string</b> in this header, but still |
| <b>std::string</b> does not get imported into |
| the global namespace (::) unless the user does |
| <b>using namespace Gtk;</b> (which is not recommended |
| practice for Gtk--, so it is not a problem). Additionally, the |
| <b>using</b>-declarations are wrapped in macros that |
| are set based on autoconf-tests to either "" or i.e. <b>using |
| std::string;</b> (depending on whether the system has |
| libstdc++ in <b>std::</b> or not). (ideas from |
| <tt><<a href="mailto:llewelly@dbritsch.dsl.xmission.com">llewelly@dbritsch.dsl.xmission.com</a>></tt>, Karl Nelson |
| <tt><<a href="mailto:kenelson@ece.ucdavis.edu">kenelson@ece.ucdavis.edu</a>></tt>) |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-emptyns"></a>Defining an empty namespace std</h3></div></div> |
| <p> |
| By defining an (empty) namespace <b>std::</b> before |
| using it, you avoid getting errors on systems where no part of the |
| library is in namespace std: |
| <pre class="programlisting"> |
| namespace std { } |
| using namespace std; |
| </pre> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-avoidfqn"></a>Avoid to use fully qualified names |
| (i.e. std::string)</h3></div></div> |
| <p> |
| If some compilers complain about <b>using |
| std::string;</b>, and if the "hack" for gtk-- mentioned above |
| does not work, then I see two solutions: |
| |
| <div class="itemizedlist"><ul type="disc"> |
| <li><p> |
| Define <b>std::</b> as a macro if the compiler |
| doesn't know about <b>std::</b>. |
| <pre class="programlisting"> |
| #ifdef OLD_COMPILER |
| #define std |
| #endif |
| </pre> |
| (thanks to Juergen Heinzl who posted this solution on |
| gnu.gcc.help) |
| </p></li> |
| <li><p> |
| Define a macro NS_STD, which is defined to |
| either "" or "std" |
| based on an autoconf-test. Then you should be able to use |
| <b>NS_STD::string</b>, which will evaluate to |
| <b>::string</b> ("string in the global namespace") on |
| systems that do not put string in std::. (This is untested) |
| </p></li> |
| </ul></div> |
| |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-osprojects"></a>How some open-source-projects deal |
| with this</h3></div></div> |
| <p> |
| This information was gathered around May 2000. It may not be correct |
| by the time you read this. |
| </p> |
| <div class="table"> |
| <p><b>Table 1. Namespace std:: in Open-Source programs</b></p> |
| <table summary="Namespace std:: in Open-Source programs" border="1"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td><a href="http://www.clanlib.org" target="_top">clanlib</a></td> |
| <td>usual</td> |
| </tr> |
| <tr> |
| <td><a href="http://pingus.seul.org" target="_top">pingus</a></td> |
| <td>usual</td> |
| </tr> |
| <tr> |
| <td><a href="http://www.mozilla.org" target="_top">mozilla</a></td> |
| <td>usual</td> |
| </tr> |
| <tr> |
| <td><a href="http://libsigc.sourceforge.net" target="_top"> |
| libsigc++</a></td> |
| <td>conservative-impl</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="table"> |
| <p><b>Table 2. Notations for categories</b></p> |
| <table summary="Notations for categories" border="1"> |
| <colgroup> |
| <col> |
| <col> |
| </colgroup> |
| <tbody> |
| <tr> |
| <td>usual</td> |
| <td>mostly fully qualified names and some |
| using-declarations (but not in headers)</td> |
| </tr> |
| <tr> |
| <td>none</td> |
| <td>no namespace std at all</td> |
| </tr> |
| <tr> |
| <td>conservative-impl</td> |
| <td>wrap all |
| namespace-handling in macros to support compilers without |
| namespace-support (no libstdc++ used in headers)</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <p> |
| 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 <a href="#sec-gtkmm-hack" title="Using namespace |
| composition if the project uses a separate |
| namespace">section on the gtkmm-hack</a>). |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-nocreate"></a>there is no ios::nocreate/ios::noreplace |
| in ISO 14882</h2></div></div> |
| <p> |
| I have seen <b>ios::nocreate</b> 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. |
| </p> |
| <p> |
| For output streams, "nocreate" is probably the default, unless you |
| specify <b>std::ios::trunc</b> ? 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 <b>app</b>, |
| <b>ate</b> and <b>trunc</b> (except for |
| <b>app</b> ?). |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-stream::attach"></a><b>stream::attach(int |
| fd)</b> is not in the standard any more</h2></div></div> |
| <p> |
| Phil Edwards <tt><<a href="mailto:pedwards@disaster.jaj.com">pedwards@disaster.jaj.com</a>></tt> 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. |
| </p> |
| <p> |
| When using libstdc++-v3, you can use |
| <div class="funcsynopsis"> |
| <pre class="funcsynopsisinfo"> |
| #include <fstream> |
| </pre> |
| <p><code><code class="funcdef"> |
| <b class="fsfunc">basic_filebuf<...>::basic_filebuf<...> |
| </b> |
| </code>(<var class="pdparam">file</var>, <var class="pdparam">mode</var>, <var class="pdparam">size</var>);<br>__c_file_type* <var class="pdparam">file</var>;<br>ios_base::open_mode <var class="pdparam">mode</var>;<br>int <var class="pdparam">size</var>;</code></p> |
| </div> |
| but the the signature of this constructor has changed often, and |
| it might change again. For the current state of this, check |
| <a href="../ext/howto.html" target="_top">the howto for extensions</a>. |
| </p> |
| <p> |
| For a portable solution (among systems which use |
| filedescriptors), you need to implement a subclass of |
| <b>std::streambuf</b> (or |
| <b>std::basic_streambuf<..></b>) which opens a file |
| given a descriptor, and then pass an instance of this to the |
| stream-constructor. For an example of this, refer to |
| <a href="http://www.josuttis.com/cppcode/fdstream.html" target="_top">fdstream example</a> |
| by Nicolai Josuttis. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-headers"></a>The new headers</h2></div></div> |
| <p> |
| All new headers can be seen in this <a href="headers_cc.txt" target="_top"> |
| source-code</a>. |
| </p> |
| <p> |
| The old C++-headers (iostream.h etc.) are available, but gcc generates |
| a warning that you are using deprecated headers. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-cheaders"></a>New headers replacing C-headers</h3></div></div> |
| <p> |
| 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 |
| <tt><math.h></tt>, you |
| should use <tt><cmath></tt>. In some cases this has |
| the advantage that the C++-header is more standardized than |
| the C-header (i.e. <tt><ctime></tt> (almost) |
| corresponds to either <tt><time.h></tt> or <tt><sys/time.h></tt>). |
| |
| The standard specifies that if you include the C-style header |
| (<tt><math.h></tt> in |
| this case), the symbols will be available both in the global |
| namespace and in namespace <b>std::</b> (but |
| libstdc++ does not yet have fully compliant headers) On the |
| other hand, if you include only the new header (i.e. <tt><cmath></tt>), the symbols |
| will only be defined in namespace <b>std::</b> |
| (and macros will be converted to inline-functions). |
| </p> |
| <p> |
| 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 <a href="http://www.cantrip.org/cheaders.html" target="_top"> |
| www.cantrip.org</a>. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h3 class="title"> |
| <a name="sec-fstream-header"></a> |
| <tt><fstream></tt> does |
| not define <b>std::cout</b>, |
| <b>std::cin</b> etc.</h3></div></div> |
| <p> |
| In earlier versions of the standard, |
| <tt><fstream.h></tt>, |
| <tt><ostream.h></tt> |
| and <tt><istream.h></tt> |
| used to define |
| <b>cout</b>, <b>cin</b> and so on. Because |
| of the templatized iostreams in libstdc++-v3, you need to include |
| <tt><iostream></tt> |
| explicitly to define these. |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-iterators"></a>Iterators</h2></div></div> |
| <p> |
| The following are not proper uses of iterators, but may be working |
| fixes for existing uses of iterators. |
| <div class="itemizedlist"><ul type="disc"> |
| <li><p>you cannot do |
| <b>ostream::operator<<(iterator)</b> to |
| print the address of the iterator => use |
| <b>operator<< &*iterator</b> instead ? |
| </p></li> |
| <li><p>you cannot clear an iterator's reference |
| (<b>iterator = 0</b>) => use |
| <b>iterator = iterator_type();</b> ? |
| </p></li> |
| <li><p> |
| <b>if (iterator)</b> won't work any |
| more => use <b>if (iterator != iterator_type())</b> |
| ?</p></li> |
| </ul></div> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-macros"></a> |
| Libc-macros (i.e. <b>isspace</b> from |
| <tt><cctype></tt>)</h2></div></div> |
| <p> |
| Glibc 2.0.x and 2.1.x define the |
| <tt><ctype.h></tt> |
| -functionality as macros (isspace, isalpha etc.). Libstdc++-v3 |
| "shadows" these macros as described in the <a href="#sec-cheaders" title="New headers replacing C-headers">section about |
| c-headers</a>. |
| </p> |
| <p> |
| 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: |
| <pre class="programlisting"> |
| #include <cctype> |
| int main() { std::isspace('X'); } |
| </pre> |
| will result in something like this (unless using g++-v3): |
| <pre class="programlisting"> |
| std:: (__ctype_b[(int) ( ( 'X' ) )] & (unsigned short int) |
| _ISspace ) ; |
| </pre> |
| </p> |
| <p> |
| 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 ?). |
| </p> |
| <p> |
| 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 <tt><ctype.h></tt> to define functions |
| instead of macros: |
| <pre class="programlisting"> |
| // This keeps isalnum, et al from being propagated as macros. |
| #if __linux__ |
| #define __NO_CTYPE 1 |
| #endif |
| |
| [ now include <ctype.h> ] |
| </pre> |
| </p> |
| <p> |
| Another problem arises if you put a <b>using namespace |
| std;</b> declaration at the top, and include <tt><ctype.h></tt>. This will result in |
| ambiguities between the definitions in the global namespace |
| (<tt><ctype.h></tt>) and the |
| definitions in namespace <b>std::</b> |
| (<b><cctype></b>). |
| </p> |
| <p> |
| The solution to this problem was posted to the libstdc++-v3 |
| mailing-list: |
| Benjamin Kosnik <tt><<a href="mailto:bkoz@redhat.com">bkoz@redhat.com</a>></tt> writes: |
| ‘ |
| --enable-cshadow-headers is currently broken. As a result, shadow |
| headers are not being searched.... |
| ’ |
| This is now outdated, but gcc 3.0 still does not have fully |
| compliant "shadow headers". |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-stream-state"></a>State of streams</h2></div></div> |
| <p> |
| At least some older implementations don't have |
| <b>std::ios_base</b>, so you should use |
| <b>std::ios::badbit</b>, <b>std::ios::failbit</b> |
| and <b>std::ios::eofbit</b> and |
| <b>std::ios::goodbit</b>. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-vector-at"></a>vector::at is missing (i.e. gcc 2.95.x)</h2></div></div> |
| <p> |
| One solution is to add an autoconf-test for this: |
| <pre class="programlisting"> |
| 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)]) |
| </pre> |
| If you are using other (non-GNU) compilers it might be a good idea |
| to check for <b>string::at</b> separately. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-eof"></a>Using std::char_traits<char>::eof()</h2></div></div> |
| <p> |
| <pre class="programlisting"> |
| #ifdef HAVE_CHAR_TRAITS |
| #define CPP_EOF std::char_traits<char>::eof() |
| #else |
| #define CPP_EOF EOF |
| #endif |
| </pre> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-string-clear"></a>Using string::clear()/string::erase()</h2></div></div> |
| <p> |
| There are two functions for deleting the contents of a string: |
| <b>clear</b> and <b>erase</b> (the latter |
| returns the string). |
| <pre class="programlisting"> |
| void |
| clear() { _M_mutate(0, this->size(), 0); } |
| </pre> |
| <pre class="programlisting"> |
| 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()); |
| } |
| </pre> |
| The implementation of <b>erase</b> seems to be more |
| complicated (from libstdc++-v3), but <b>clear</b> is not |
| implemented in gcc 2.95.x's libstdc++, so you should use |
| <b>erase</b> (which is probably faster than |
| <b>operator=(charT*)</b>). |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-scan-form"></a>GNU Extensions ostream::form and istream::scan</h2></div></div> |
| <p> |
| These are not supported any more - use |
| <a href="#sec-stringstream" title="Using stringstreams"> |
| stringstreams</a> instead. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-stringstream"></a>Using stringstreams</h2></div></div> |
| <p> |
| Libstdc++-v3 provides the new |
| <b>i/ostringstream</b>-classes, (<tt><sstream></tt>), but for compatibility |
| with older implementations you still have to use |
| <b>i/ostrstream</b> (<tt><strstream></tt>): |
| <pre class="programlisting"> |
| #ifdef HAVE_SSTREAM |
| #include <sstream> |
| #else |
| #include <strstream> |
| #endif |
| </pre> |
| <div class="itemizedlist"><ul type="disc"> |
| <li><p> <b>strstream</b> is considered to be |
| deprecated |
| </p></li> |
| <li><p> <b>strstream</b> is limited to |
| <b>char</b> |
| </p></li> |
| <li><p> with <b>ostringstream</b> you don't |
| have to take care of terminating the string or freeing its |
| memory |
| </p></li> |
| <li><p> <b>istringstream</b> can be re-filled |
| (clear(); str(input);) |
| </p></li> |
| </ul></div> |
| </p> |
| <p> |
| You can then use output-stringstreams like this: |
| <pre class="programlisting"> |
| #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 |
| </pre> |
| </p> |
| <p> |
| Input-stringstreams can be used similarly: |
| <pre class="programlisting"> |
| std::string input; |
| ... |
| #ifdef HAVE_SSTREAM |
| std::istringstream iss(input); |
| #else |
| std::istrstream iss(input.c_str()); |
| #endif |
| int i; |
| iss >> i; |
| </pre> |
| One (the only?) restriction is that an istrstream cannot be re-filled: |
| <pre class="programlisting"> |
| std::istringstream iss(numerator); |
| iss >> m_num; |
| // this is not possible with istrstream |
| iss.clear(); |
| iss.str(denominator); |
| iss >> m_den; |
| </pre> |
| If you don't care about speed, you can put these conversions in |
| a template-function: |
| <pre class="programlisting"> |
| 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; |
| } |
| </pre> |
| Another example of using stringstreams is in <a href="../21_strings/howto.html" target="_top">this howto</a>. |
| </p> |
| <p> |
| 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. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><h2 class="title" style="clear: both"> |
| <a name="sec-about"></a>About...</h2></div></div> |
| <p> |
| Please send any experience, additions, corrections or questions to |
| <a href="mailto:fnatter@gmx.net" target="_top">fnatter@gmx.net</a> or for |
| discussion to the libstdc++-v3-mailing-list. |
| </p> |
| </div> |
| </div></body> |
| </html> |