mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-22 10:09:09 +08:00
e0b7ed05b2
2000-09-08 Felix Natter <fnatter@gmx.net> * docs/17_intro/porting-howto.html: New version. From-SVN: r36275
727 lines
25 KiB
HTML
727 lines
25 KiB
HTML
<html>
|
|
<head>
|
|
<title>Libstdc++-porting-howto</title>
|
|
<meta content="DocBook XSL Stylesheets V1.16" name="generator">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<div class="article" id="libstdporting">
|
|
<div class="titlepage">
|
|
<h1 class="title">
|
|
<a name="libstdporting">Libstdc++-porting-howto</a>
|
|
</h1>
|
|
<h3 class="author">Felix Natter</h3>
|
|
<p>
|
|
This document can be distributed under the FDL
|
|
(<a href="http://www.gnu.org">www.gnu.org</a>)
|
|
</p>
|
|
<p class="pubdate">what kind of a date ? I don't drink !</p>
|
|
<div class="revhistory">
|
|
<table width="100%" border="1">
|
|
<tr>
|
|
<th colspan="3" valign="top" align="left"><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 colspan="3" align="left">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 colspan="3" align="left">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 colspan="3" align="left">5 new sections.</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="abstract">
|
|
<p>
|
|
<a name="N2688"></a><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>
|
|
<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 <i>namespace
|
|
composition</i> 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"><b>stream::attach(int
|
|
fd)</b> 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">
|
|
<tt><fstream></tt> does
|
|
not define <b>std::cout</b>,
|
|
<b>std::cin</b> etc.</a>
|
|
</dt>
|
|
</dl>
|
|
</dd>
|
|
<dt>5. <a href="#sec-iterators">Iterators</a>
|
|
</dt>
|
|
<dt>6. <a href="#sec-macros">
|
|
Libc-macros (i.e. <b>isspace</b> from
|
|
<tt><cctype></tt>)</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.2)</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-stringstream">Using stringstream's</a>
|
|
</dt>
|
|
<dt>12. <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" id="sec-nsstd">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-nsstd"><b>1. Namespace std::</b></a>
|
|
</h2>
|
|
<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>
|
|
<li>
|
|
<a name="N2712"></a>
|
|
<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>
|
|
<a name="N2721"></a>
|
|
<p>put a kind of
|
|
<i>using-declaration</i> 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>
|
|
<a name="N2736"></a>
|
|
<p>use a <i>fully qualified name</i> 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" id="sec-gtkmm-hack">
|
|
<h3 class="title">
|
|
<a name="sec-gtkmm-hack"><b>1.1.1. Using <i>namespace
|
|
composition</i> if the project uses a separate
|
|
namespace</b></a>
|
|
</h3>
|
|
<p>
|
|
<a href="http://gtkmm.sourceforge.net">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
|
|
<i>namespace composition</i>. This is what happens if
|
|
you put a <i>using</i>-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
|
|
user-space (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" id="sec-emptyns">
|
|
<h3 class="title">
|
|
<a name="sec-emptyns"><b>1.1.2. Defining an empty namespace std</b></a>
|
|
</h3>
|
|
<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" id="sec-avoidfqn">
|
|
<h3 class="title">
|
|
<a name="sec-avoidfqn"><b>1.1.3. Avoid to use fully qualified names
|
|
(i.e. std::string)</b></a>
|
|
</h3>
|
|
<p>
|
|
If some compilers complain about <b>using
|
|
std::string;</b>, 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
|
|
<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>
|
|
</div>
|
|
<div class="section" id="sec-osprojects">
|
|
<h3 class="title">
|
|
<a name="sec-osprojects"><b>1.1.4. How some open-source-projects deal
|
|
with this</b></a>
|
|
</h3>
|
|
<p>
|
|
This information was gathered around May 2000. It may not be correct
|
|
by the time you read this.
|
|
</p>
|
|
<div class="table">
|
|
<p>
|
|
<a name="N2901"></a><b>Table 1. Namespace std:: in Open-Source programs</b>
|
|
</p>
|
|
<table border="1">
|
|
<colgroup>
|
|
<col>
|
|
<col>
|
|
</colgroup>
|
|
<tbody>
|
|
<tr>
|
|
<td><a href="http://www.clanlib.org">clanlib</a></td><td>usual</td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="http://pingus.seul.org">pingus</a></td><td>usual</td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="http://www.mozilla.org">mozilla</a></td><td>usual</td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="http://www.mnemonic.org">mnemonic</a></td><td>none</td>
|
|
</tr>
|
|
<tr>
|
|
<td><a href="http://libsigc.sourceforge.net">
|
|
libsigc++</a></td><td>conservative-impl</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="table">
|
|
<p>
|
|
<a name="N2978"></a><b>Table 2. Notations for categories</b>
|
|
</p>
|
|
<table 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="#"></a>).
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="sec-nocreate">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-nocreate"><b>2. there is no ios::nocreate/ios::noreplace
|
|
in ISO 14882</b></a>
|
|
</h2>
|
|
<p>
|
|
I have seen <b>ios::nocreate</b> 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.
|
|
</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" id="sec-stream::attach">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-stream::attach"><b>3. <b>stream::attach(int
|
|
fd)</b> is not in the standard any more</b></a>
|
|
</h2>
|
|
<p>
|
|
When using libstdc++-v3, you can use
|
|
<div id="N3082" class="funcsynopsis">
|
|
<p>
|
|
</p>
|
|
<a name="N3082"></a>
|
|
<pre class="funcsynopsisinfo">
|
|
#include <fstream>
|
|
</pre>
|
|
<p>
|
|
<code><code class="funcdef">int <b class="fsfunc">basic_filebuf</b></code>(<var class="pdparam">__fd</var>, <var class="pdparam">__name</var>, <var class="pdparam">__mode</var>);<br>int <var class="pdparam">__fd</var>;<br>const char* <var class="pdparam">__name</var>;<br>ios_base::openmode <var class="pdparam">__mode</var>;</code>
|
|
</p>
|
|
<p>
|
|
</p>
|
|
</div>
|
|
For a portable solution (if there is one), you need to implement a
|
|
subclass of <b>streambuf</b> which opens a file given a
|
|
descriptor, and then pass an instance of this to the
|
|
stream-constructor (from the Josuttis-book).
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-headers">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-headers"><b>4. The new headers</b></a>
|
|
</h2>
|
|
<p>
|
|
All new headers can be seen in this <a href="../../testsuite/17_intro/headers.cc">source-code</a>.
|
|
</p>
|
|
<p>
|
|
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).
|
|
</p>
|
|
<div class="section" id="sec-cheaders">
|
|
<h3 class="title">
|
|
<a name="sec-cheaders"><b>4.4.1. New headers replacing C-headers</b></a>
|
|
</h3>
|
|
<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, ommiting the extension
|
|
(.h). For example, instead of using <tt><math.h></tt>, you should use <tt><cmath></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> (libstdc++-v3, version 2.90.8 currently
|
|
puts them in <b>std::</b> only) On the other hand, if
|
|
you include only the new header (i.e. <tt><pcmath></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 reuses ("shadows") the C library-functions, have
|
|
a look at <a href="http://www.cantrip.org/cheaders.html">
|
|
www.cantrip.org</a>.
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-fstream-header">
|
|
<h3 class="title">
|
|
<a name="sec-fstream-header"><b>4.4.2.
|
|
<tt><fstream></tt> does
|
|
not define <b>std::cout</b>,
|
|
<b>std::cin</b> etc.</b></a>
|
|
</h3>
|
|
<p>
|
|
In previous 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" id="sec-iterators">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-iterators"><b>5. Iterators</b></a>
|
|
</h2>
|
|
<p>
|
|
The following are not proper uses of iterators, but may be working
|
|
fixes for existing uses of iterators.
|
|
<div class="itemizedlist">
|
|
<ul>
|
|
<li>
|
|
<a name="N3282"></a>
|
|
<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>
|
|
<a name="N3303"></a>
|
|
<p>you cannot clear an iterator's reference
|
|
(<b>iterator = 0</b>) => use
|
|
<b>iterator = iterator_type();</b> ?
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<a name="N3316"></a>
|
|
<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" id="sec-macros">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-macros"><b>6.
|
|
Libc-macros (i.e. <b>isspace</b> from
|
|
<tt><cctype></tt>)</b></a>
|
|
</h2>
|
|
<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="#"></a>.
|
|
</p>
|
|
<p>
|
|
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:
|
|
<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.2) 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....
|
|
"
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-stream-state">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-stream-state"><b>7.
|
|
State of streams
|
|
</b></a>
|
|
</h2>
|
|
<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" id="sec-vector-at">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-vector-at"><b>8. vector::at is missing (i.e. gcc 2.95.2)</b></a>
|
|
</h2>
|
|
<p>
|
|
For my use, I added it to
|
|
<tt>prefix/include/g++-3/stl_vector.h</tt>:
|
|
<pre class="programlisting">
|
|
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);
|
|
}
|
|
</pre>
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-eof">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-eof"><b>9. Using std::char_traits<char>::eof()</b></a>
|
|
</h2>
|
|
<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" id="sec-string-clear">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-string-clear"><b>10. Using string::clear()/string::erase()</b></a>
|
|
</h2>
|
|
<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.2's libstdc++, so you should use
|
|
<b>erase</b> (which is probably faster than
|
|
<b>operator=(charT*)</b>).
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-stringstream">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-stringstream"><b>11. Using stringstream's</b></a>
|
|
</h2>
|
|
<p>
|
|
Libstdc++-v3 includes the new
|
|
<b>i/ostringstream</b>-classes, (<tt><sstream></tt>), but 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>
|
|
<li>
|
|
<a name="N3595"></a>
|
|
<p> <b>strstream</b> is considered to be
|
|
deprecated
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<a name="N3603"></a>
|
|
<p> <b>strstream</b> is limited to
|
|
<b>char</b>
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<a name="N3614"></a>
|
|
<p> with <b>ostringstream</b> you don't
|
|
have to take care of terminating the string or freeing its
|
|
memory
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<a name="N3622"></a>
|
|
<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>
|
|
</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.2
|
|
uses.
|
|
</p>
|
|
</div>
|
|
<div class="section" id="sec-about">
|
|
<h2 class="title" style="clear: all">
|
|
<a name="sec-about"><b>12. About...</b></a>
|
|
</h2>
|
|
<p>
|
|
Please send any experience, additions, corrections or questions to
|
|
<a href="mailto:fnatter@gmx.net">fnatter@gmx.net</a> or for
|
|
discussion to the libstdc++-v3-mailing-list.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|