| <?xml version="1.0" encoding="ISO-8859-1"?> |
| |
| <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1//EN" |
| "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd"> |
| |
| <?xml-stylesheet type="text/xsl" href="docbook-xslt/docbook/html/docbook.xsl"?> |
| |
| <!-- |
| This is written using docbook 4.1 xml. HTML is generated using |
| the xslt-stylesheets from http://www.nwalsh.com. |
| |
| xsltproc is an xslt-processor included in libxslt: |
| (http://xmlsoft.org/XSLT/ or here: |
| ftp://ftp.gnome.org/pub/GNOME/unstable/sources/libxslt/) |
| (it requires libxml2: http://xmlsoft.org |
| or here: ftp://ftp.gnome.org/pub/GNOME/stable/sources/libxml/) |
| |
| You can find the latest version of this document here: |
| http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/porting-howto(.html|.xml) |
| --> |
| |
| <!-- TODO: |
| o remove //@label: use automatic numbering |
| o make this work: <link linkend="sec-gtkmm-hack" endterm="sec-gtkmm-hack.title"/>. |
| o clean up the section-numbering |
| --> |
| |
| <article class = "whitepaper" id = "libstdc++-porting-howto" lang = "en"> |
| <articleinfo> |
| <title>Libstdc++-porting-howto</title> |
| <author> |
| <firstname>Felix</firstname> |
| <surname>Natter</surname> |
| </author> |
| <address> |
| <email>fnatter@gmx.net</email> |
| </address> |
| <revhistory> |
| <revision> |
| <revnumber>0.5</revnumber> |
| <date>Thu Jun 1 13:06:50 2000</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark>First docbook-version.</revremark> |
| </revision> |
| <revision> |
| <revnumber>0.8</revnumber> |
| <date>Sun Jul 30 20:28:40 2000</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark>First released version using docbook-xml |
| + second upload to libstdc++-page. |
| </revremark> |
| </revision> |
| <revision> |
| <revnumber>0.9</revnumber> |
| <date>Wed Sep 6 02:59:32 2000</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark>5 new sections.</revremark> |
| </revision> |
| <revision> |
| <revnumber>0.9.1</revnumber> |
| <date>Sat Sep 23 14:20:15 2000</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark>added information about why file-descriptors are not in the |
| standard</revremark> |
| </revision> |
| <revision> |
| <revnumber>0.9.2</revnumber> |
| <date>Tue Jun 5 20:07:49 2001</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark> |
| a fix, added hint on increased portability of C-shadow-headers, |
| added autoconf-test HAVE_CONTAINER_AT |
| </revremark> |
| </revision> |
| <revision> |
| <revnumber>0.9.3</revnumber> |
| <date>Fri Jun 29 16:15:56 2001</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark> |
| 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 |
| </revremark> |
| </revision> |
| <revision> |
| <revnumber>0.9.4</revnumber> |
| <date>Mon Nov 5 17:01:04 2001</date> |
| <authorinitials>fnatter</authorinitials> |
| <revremark> |
| rewrite section 1.1.3 because of gnu.gcc.help-post by |
| Juergen Heinzl |
| </revremark> |
| </revision> |
| </revhistory> |
| <legalnotice><title>Legal Notice</title> |
| <para> |
| This document can be distributed under the FDL |
| (<ulink url = "http://www.gnu.org">www.gnu.org</ulink>) |
| </para> |
| </legalnotice> |
| |
| <pubdate>Tue Jun 5 20:07:49 2001</pubdate> |
| <abstract> |
| <para> |
| 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. |
| </para> |
| </abstract> |
| </articleinfo> |
| |
| <para> |
| 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". |
| </para> |
| |
| <section id="sec-nsstd" label="1"><title>Namespace std::</title> |
| <para> |
| 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: |
| <itemizedlist> |
| |
| <listitem><para>wrap your code in <command>namespace std { |
| ... }</command> => This is not an option because only symbols |
| from the standard c++-library are defined in namespace std::. |
| </para></listitem> |
| |
| <listitem><para>put a kind of |
| <emphasis>using-declaration</emphasis> in your source (either |
| <command>using namespace std;</command> or i.e. <command>using |
| std::string;</command>) => works well for source-files, but |
| cannot be used in header-files. |
| </para></listitem> |
| |
| <listitem><para>use a <emphasis>fully qualified name</emphasis> for |
| each libstdc++-symbol (i.e. <command>std::string</command>, |
| <command>std::cout</command>) => can always be used |
| </para></listitem> |
| </itemizedlist> |
| </para> |
| |
| <para> |
| Because there are many compilers which still use an implementation |
| that does not have the standard C++-library in namespace |
| <command>std::</command>, some care is required to support these as |
| well. |
| </para> |
| |
| <para> |
| Namespace back-portability-issues are generally not a problem with |
| g++, because versions of g++ that do not have libstdc++ in |
| <command>std::</command> use <command>-fno-honor-std</command> |
| (ignore <command>std::</command>, <command>:: = std::</command>) by |
| default. That is, the responsibility for enabling or disabling |
| <command>std::</command> is on the user; the maintainer does not have |
| to care about it. This probably applies to some other compilers as |
| well. |
| </para> |
| <para> |
| The following sections list some possible solutions to support compilers |
| that cannot ignore std::. |
| </para> |
| |
| <section id = "sec-gtkmm-hack" label = "1.1"> |
| <title id="sec-gtkmm-hack.title">Using <emphasis>namespace |
| composition</emphasis> if the project uses a separate |
| namespace</title> |
| <para> |
| <ulink url = "http://gtkmm.sourceforge.net">Gtk--</ulink> defines |
| most of its classes in namespace Gtk::. Thus, it was possible to |
| adapt Gtk-- to namespace std:: by using a C++-feature called |
| <emphasis>namespace composition</emphasis>. This is what happens if |
| you put a <emphasis>using</emphasis>-declaration into a |
| namespace-definition: the imported symbol(s) gets imported into the |
| currently active namespace(s). For example: |
| <programlisting> |
| namespace Gtk { |
| using std::string; |
| class Window { ... } |
| } |
| </programlisting> |
| In this example, <command>std::string</command> gets imported into |
| namespace Gtk::. The result is that you don't have to use |
| <command>std::string</command> in this header, but still |
| <command>std::string</command> does not get imported into |
| the global namespace (::) unless the user does |
| <command>using namespace Gtk;</command> (which is not recommended |
| practice for Gtk--, so it is not a problem). Additionally, the |
| <command>using</command>-declarations are wrapped in macros that |
| are set based on autoconf-tests to either "" or i.e. <command>using |
| std::string;</command> (depending on whether the system has |
| libstdc++ in <command>std::</command> or not). (ideas from |
| <email>llewelly@dbritsch.dsl.xmission.com</email>, Karl Nelson |
| <email>kenelson@ece.ucdavis.edu</email>) |
| </para> |
| </section> |
| |
| <section id = "sec-emptyns" label = "1.2"> |
| <title id="sec-emptyns.title">Defining an empty namespace std</title> |
| <para> |
| By defining an (empty) namespace <command>std::</command> before |
| using it, you avoid getting errors on systems where no part of the |
| library is in namespace std: |
| <programlisting> |
| namespace std { } |
| using namespace std; |
| </programlisting> |
| </para> |
| </section> |
| |
| <section id = "sec-avoidfqn" label = "1.3"> |
| <title id="sec-avoidfqn.title">Avoid to use fully qualified names |
| (i.e. std::string)</title> |
| <para> |
| If some compilers complain about <command>using |
| std::string;</command>, and if the "hack" for gtk-- mentioned above |
| does not work, then I see two solutions: |
| |
| <itemizedlist> |
| <listitem><para> |
| Define <command>std::</command> as a macro if the compiler |
| doesn't know about <command>std::</command>. |
| <programlisting> |
| #ifdef OLD_COMPILER |
| #define std |
| #endif |
| </programlisting> |
| (thanks to Juergen Heinzl who posted this solution on |
| gnu.gcc.help) |
| </para></listitem> |
| |
| <listitem><para> |
| Define a macro <symbol>NS_STD</symbol>, which is defined to |
| either "" or "std" |
| based on an autoconf-test. Then you should be able to use |
| <command>NS_STD::string</command>, which will evaluate to |
| <command>::string</command> ("string in the global namespace") on |
| systems that do not put string in std::. (This is untested) |
| </para></listitem> |
| </itemizedlist> |
| |
| </para> |
| </section> |
| |
| <section id = "sec-osprojects" label = "1.4"> |
| <title id="sec-osprojects.title">How some open-source-projects deal |
| with this</title> |
| <para> |
| This information was gathered around May 2000. It may not be correct |
| by the time you read this. |
| </para> |
| <table><title>Namespace std:: in Open-Source programs</title> |
| <tgroup cols = "2"> |
| <tbody> |
| <row> |
| <entry><ulink url = "http://www.clanlib.org">clanlib</ulink> |
| </entry> |
| <entry>usual</entry> |
| </row> |
| <row> |
| <entry><ulink url = "http://pingus.seul.org">pingus</ulink> |
| </entry> |
| <entry>usual</entry> |
| </row> |
| <row> |
| <entry><ulink url = "http://www.mozilla.org">mozilla</ulink> |
| </entry> |
| <entry>usual</entry> |
| </row> |
| <row> |
| <entry><ulink url = "http://libsigc.sourceforge.net"> |
| libsigc++</ulink></entry> |
| <entry>conservative-impl</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <table><title>Notations for categories</title> |
| <tgroup cols = "2"> |
| <tbody> |
| <row> |
| <entry>usual</entry> |
| <entry>mostly fully qualified names and some |
| using-declarations (but not in headers)</entry> |
| </row> |
| <row> |
| <entry>none</entry> <entry>no namespace std at all</entry> |
| </row> |
| <row> |
| <entry>conservative-impl</entry> |
| <entry>wrap all |
| namespace-handling in macros to support compilers without |
| namespace-support (no libstdc++ used in headers)</entry> |
| </row> |
| </tbody> |
| </tgroup> |
| </table> |
| |
| <para> |
| 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 <link linkend="sec-gtkmm-hack" |
| endterm="sec-gtkmm-hack.title">section on the gtkmm-hack</link>). |
| </para> |
| </section> |
| </section> <!-- end of namespace-section --> |
| |
| <section id = "sec-nocreate" label = "2"> |
| <title id="sec-nocreate.title">there is no ios::nocreate/ios::noreplace |
| in ISO 14882</title> |
| <para> |
| I have seen <command>ios::nocreate</command> 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. |
| </para> |
| <para> |
| For output streams, "nocreate" is probably the default, unless you |
| specify <command>std::ios::trunc</command> ? 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 <command>app</command>, |
| <command>ate</command> and <command>trunc</command> (except for |
| <command>app</command> ?). |
| </para> |
| </section> |
| |
| <section id = "sec-stream::attach" label = "3"> |
| <title id="sec-stream::attach.title"><command>stream::attach(int |
| fd)</command> is not in the standard any more</title> |
| <para> |
| Phil Edwards <email>pedwards@disaster.jaj.com</email> 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. |
| </para> |
| <para> |
| When using libstdc++-v3, you can use |
| <funcsynopsis> |
| <funcsynopsisinfo format="linespecific"> |
| #include <fstream> |
| </funcsynopsisinfo> |
| <funcprototype> |
| <funcdef> |
| <function>basic_filebuf<...>::basic_filebuf<...> |
| </function> |
| </funcdef> |
| <paramdef>__c_file_type* <parameter>file</parameter></paramdef> |
| <paramdef>ios_base::open_mode <parameter>mode</parameter></paramdef> |
| <paramdef>int <parameter>size</parameter></paramdef> |
| </funcprototype> |
| </funcsynopsis> |
| but the the signature of this constructor has changed often, and |
| it might change again. For the current state of this, check |
| <ulink url="../ext/howto.html">the howto for extensions</ulink>. |
| </para> |
| <para> |
| For a portable solution (among systems which use |
| filedescriptors), you need to implement a subclass of |
| <command>std::streambuf</command> (or |
| <command>std::basic_streambuf<..></command>) 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 |
| <ulink url="http://www.josuttis.com/cppcode/fdstream.html">fdstream example</ulink> |
| by Nicolai Josuttis. |
| </para> |
| </section> |
| |
| <section id = "sec-headers" label = "4"> |
| <title id="sec-headers.title">The new headers</title> |
| <para> |
| All new headers can be seen in this <ulink url="headers_cc.txt"> |
| source-code</ulink>. |
| </para> |
| <para> |
| The old C++-headers (iostream.h etc.) are available, but gcc generates |
| a warning that you are using deprecated headers. |
| </para> |
| |
| <section id = "sec-cheaders" label = "4.1"> |
| <title id="sec-cheaders.title">New headers replacing C-headers</title> |
| <para> |
| 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 |
| <filename class="headerfile"><math.h></filename>, you |
| should use <filename class = |
| "headerfile"><cmath></filename>. In some cases this has |
| the advantage that the C++-header is more standardized than |
| the C-header (i.e. <filename |
| class="headerfile"><ctime></filename> (almost) |
| corresponds to either <filename class = |
| "headerfile"><time.h></filename> or <filename class = |
| "headerfile"><sys/time.h></filename>). |
| |
| The standard specifies that if you include the C-style header |
| (<filename class = "headerfile"><math.h></filename> in |
| this case), the symbols will be available both in the global |
| namespace and in namespace <command>std::</command> (but |
| libstdc++ does not yet have fully compliant headers) On the |
| other hand, if you include only the new header (i.e. <filename |
| class = "headerfile"><cmath></filename>), the symbols |
| will only be defined in namespace <command>std::</command> |
| (and macros will be converted to inline-functions). |
| </para> |
| <para> |
| 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 <ulink |
| url="http://www.cantrip.org/cheaders.html"> |
| www.cantrip.org</ulink>. |
| </para> |
| </section> |
| |
| <section id = "sec-fstream-header" label = "4.2"> |
| <title id="sec-fstream-header.title"> |
| <filename class="headerfile"><fstream></filename> does |
| not define <command>std::cout</command>, |
| <command>std::cin</command> etc.</title> |
| <para> |
| In earlier versions of the standard, |
| <filename class="headerfile"><fstream.h></filename>, |
| <filename class="headerfile"><ostream.h></filename> |
| and <filename class="headerfile"><istream.h></filename> |
| used to define |
| <command>cout</command>, <command>cin</command> and so on. Because |
| of the templatized iostreams in libstdc++-v3, you need to include |
| <filename class = "headerfile"><iostream></filename> |
| explicitly to define these. |
| </para> |
| </section> |
| </section> |
| |
| <section id = "sec-iterators" label = "5"> |
| <title id="sec-iterators.title">Iterators</title> |
| <para> |
| The following are not proper uses of iterators, but may be working |
| fixes for existing uses of iterators. |
| <itemizedlist> |
| <listitem><para>you cannot do |
| <command>ostream::operator<<(iterator)</command> to |
| print the address of the iterator => use |
| <command>operator<< &*iterator</command> instead ? |
| </para> |
| </listitem> |
| <listitem><para>you cannot clear an iterator's reference |
| (<command>iterator = 0</command>) => use |
| <command>iterator = iterator_type();</command> ? |
| </para> |
| </listitem> |
| <listitem><para><command>if (iterator)</command> won't work any |
| more => use <command>if (iterator != iterator_type())</command> |
| ?</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </section> |
| |
| <section id = "sec-macros" label = "6"> |
| <title id="sec-macros.title"> |
| Libc-macros (i.e. <command>isspace</command> from |
| <filename class = "headerfile"><cctype></filename>)</title> |
| <para> |
| Glibc 2.0.x and 2.1.x define the |
| <filename class="headerfile"><ctype.h></filename> |
| -functionality as macros (isspace, isalpha etc.). Libstdc++-v3 |
| "shadows" these macros as described in the <link |
| linkend="sec-cheaders" endterm="sec-cheaders.title">section about |
| c-headers</link>. |
| </para> |
| <para> |
| 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: |
| <programlisting> |
| #include <cctype> |
| int main() { std::isspace('X'); } |
| </programlisting> |
| will result in something like this (unless using g++-v3): |
| <programlisting> |
| std:: (__ctype_b[(int) ( ( 'X' ) )] & (unsigned short int) |
| _ISspace ) ; |
| </programlisting> |
| </para> |
| <para> |
| 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 ?). |
| </para> |
| <para> |
| 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 <filename |
| class="headerfile"><ctype.h></filename> to define functions |
| instead of macros: |
| <programlisting> |
| // This keeps isalnum, et al from being propagated as macros. |
| #if __linux__ |
| #define __NO_CTYPE 1 |
| #endif |
| |
| [ now include <ctype.h> ] |
| </programlisting> |
| </para> |
| <para> |
| Another problem arises if you put a <command>using namespace |
| std;</command> declaration at the top, and include <filename class |
| = "headerfile"><ctype.h></filename>. This will result in |
| ambiguities between the definitions in the global namespace |
| (<filename class = "headerfile"><ctype.h></filename>) and the |
| definitions in namespace <command>std::</command> |
| (<command><cctype></command>). |
| </para> |
| <para> |
| The solution to this problem was posted to the libstdc++-v3 |
| mailing-list: |
| Benjamin Kosnik <email>bkoz@redhat.com</email> writes: |
| <quote> |
| --enable-cshadow-headers is currently broken. As a result, shadow |
| headers are not being searched.... |
| </quote> |
| This is now outdated, but gcc 3.0 still does not have fully |
| compliant "shadow headers". |
| </para> |
| </section> |
| |
| <section id="sec-stream-state" label="7"> |
| <title id="sec-stream-state.title">State of streams</title> |
| <para> |
| At least some older implementations don't have |
| <command>std::ios_base</command>, so you should use |
| <command>std::ios::badbit</command>, <command>std::ios::failbit</command> |
| and <command>std::ios::eofbit</command> and |
| <command>std::ios::goodbit</command>. |
| </para> |
| </section> |
| |
| <section id="sec-vector-at" label="8"> |
| <title>vector::at is missing (i.e. gcc 2.95.x)</title> |
| <para> |
| One solution is to add an autoconf-test for this: |
| <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)]) |
| </programlisting> |
| If you are using other (non-GNU) compilers it might be a good idea |
| to check for <command>string::at</command> separately. |
| </para> |
| </section> |
| |
| <section id="sec-eof" label="9"> |
| <title>Using std::char_traits<char>::eof()</title> |
| <para> |
| <programlisting> |
| #ifdef HAVE_CHAR_TRAITS |
| #define CPP_EOF std::char_traits<char>::eof() |
| #else |
| #define CPP_EOF EOF |
| #endif |
| </programlisting> |
| </para> |
| </section> |
| |
| <section id="sec-string-clear" label="10"> |
| <title>Using string::clear()/string::erase()</title> |
| <para> |
| There are two functions for deleting the contents of a string: |
| <command>clear</command> and <command>erase</command> (the latter |
| returns the string). |
| <programlisting> |
| void |
| clear() { _M_mutate(0, this->size(), 0); } |
| </programlisting> |
| <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()); |
| } |
| </programlisting> |
| The implementation of <command>erase</command> seems to be more |
| complicated (from libstdc++-v3), but <command>clear</command> is not |
| implemented in gcc 2.95.x's libstdc++, so you should use |
| <command>erase</command> (which is probably faster than |
| <command>operator=(charT*)</command>). |
| </para> |
| </section> |
| |
| <section id="sec-scan-form" label="11"> |
| <title>GNU Extensions ostream::form and istream::scan</title> |
| <para> |
| These are not supported any more - use |
| <link linkend="sec-stringstream" endterm="sec-stringstream.title"> |
| stringstreams</link> instead. |
| </para> |
| </section> |
| |
| <section id="sec-stringstream" label="12"> |
| <title>Using stringstreams</title> |
| <para> |
| Libstdc++-v3 provides the new |
| <command>i/ostringstream</command>-classes, (<filename |
| class="headerfile"><sstream></filename>), but for compatibility |
| with older implementations you still have to use |
| <command>i/ostrstream</command> (<filename |
| class="headerfile"><strstream></filename>): |
| <programlisting> |
| #ifdef HAVE_SSTREAM |
| #include <sstream> |
| #else |
| #include <strstream> |
| #endif |
| </programlisting> |
| <itemizedlist> |
| <listitem><para> <command>strstream</command> is considered to be |
| deprecated |
| </para> |
| </listitem> |
| <listitem><para> <command>strstream</command> is limited to |
| <command>char</command> |
| </para> |
| </listitem> |
| <listitem><para> with <command>ostringstream</command> you don't |
| have to take care of terminating the string or freeing its |
| memory |
| </para> |
| </listitem> |
| <listitem><para> <command>istringstream</command> can be re-filled |
| (clear(); str(input);) |
| </para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| <para> |
| You can then use output-stringstreams like this: |
| <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 |
| </programlisting> |
| </para> |
| <para> |
| Input-stringstreams can be used similarly: |
| <programlisting> |
| std::string input; |
| ... |
| #ifdef HAVE_SSTREAM |
| std::istringstream iss(input); |
| #else |
| std::istrstream iss(input.c_str()); |
| #endif |
| int i; |
| iss >> i; |
| </programlisting> |
| One (the only?) restriction is that an istrstream cannot be re-filled: |
| <programlisting> |
| std::istringstream iss(numerator); |
| iss >> m_num; |
| // this is not possible with istrstream |
| iss.clear(); |
| iss.str(denominator); |
| iss >> m_den; |
| </programlisting> |
| If you don't care about speed, you can put these conversions in |
| a template-function: |
| <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; |
| } |
| </programlisting> |
| Another example of using stringstreams is in <ulink |
| url="../21_strings/howto.html">this howto</ulink>. |
| </para> |
| <para> |
| 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. |
| </para> |
| </section> |
| |
| <section id = "sec-about" label="13"> |
| <title id="sec-about.title">About...</title> |
| <para> |
| Please send any experience, additions, corrections or questions to |
| <ulink url = "mailto:fnatter@gmx.net">fnatter@gmx.net</ulink> or for |
| discussion to the libstdc++-v3-mailing-list. |
| </para> |
| </section> |
| |
| </article> |
| |
| <!-- this is now obsolete, since the nwalsh-stylesheet generates an index |
| <para> |
| <itemizedlist> |
| <listitem><para> |
| <link linkend = "sec-nsstd" endterm = "sec-nsstd.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-nocreate" endterm = "sec-nocreate.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-stream::attach" |
| endterm = "sec-stream::attach.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-headers" endterm = "sec-headers.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-iterators" endterm = "sec-iterators.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-macros" endterm = "sec-macros.title"/> |
| </para></listitem> |
| <listitem><para> |
| <link linkend = "sec-about" endterm = "sec-about.title"/> |
| </para></listitem> |
| </itemizedlist> |
| </para> |
| --> |
| |
| <!-- |
| Local Variables: |
| compile-command: "xsltproc -o porting-howto.html docbook-xslt/docbook/html/docbook.xsl porting-howto.xml" |
| End: |
| --> |