<!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 thestandard</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 andupdate the section on filebuf::attach to point to ../ext/howto.html,added link to ../21/strings/howto.htmlin 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-headersadd section about ostream::form and istream::scansec-vector-at: remove hint to modify headersfix 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 byJuergen 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 earlierversions) to libstdc++-v3. Not speaking in terms of the GNU libstdc++implementations, this means porting from earlier versions of theC++-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 namespacecomposition if the project uses a separatenamespace</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 dealwith this</a></dt></dl></dd><dt>2. <a href="#sec-nocreate">there is no ios::nocreate/ios::noreplacein ISO 14882</a></dt><dt>3. <a href="#sec-stream::attach">stream::attach(intfd) 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> doesnot 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 ISO14882-implementations". On the other hand, if I say "backportable" or"conservative", I am talking about "compiles with olderlibstdc++-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 standardC++-library is defined in namespace std::. Thus, in order to useclasses from the standard C++-library, you can do one of threethings:<div class="itemizedlist"><ul type="disc"><li><p>wrap your code in <b>namespace std {... }</b> => This is not an option because only symbolsfrom 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>usingstd::string;</b>) => works well for source-files, butcannot be used in header-files.</p></li><li><p>use a <span class="emphasis"><i>fully qualified name</i></span> foreach 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 implementationthat does not have the standard C++-library in namespace<b>std::</b>, some care is required to support these aswell.</p><p>Namespace back-portability-issues are generally not a problem withg++, 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>) bydefault. That is, the responsibility for enabling or disabling<b>std::</b> is on the user; the maintainer does not haveto care about it. This probably applies to some other compilers aswell.</p><p>The following sections list some possible solutions to support compilersthat 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>namespacecomposition</i></span> if the project uses a separatenamespace</h3></div></div><p><a href="http://gtkmm.sourceforge.net" target="_top">Gtk--</a> definesmost of its classes in namespace Gtk::. Thus, it was possible toadapt Gtk-- to namespace std:: by using a C++-feature called<span class="emphasis"><i>namespace composition</i></span>. This is what happens ifyou put a <span class="emphasis"><i>using</i></span>-declaration into anamespace-definition: the imported symbol(s) gets imported into thecurrently 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 intonamespace 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 intothe global namespace (::) unless the user does<b>using namespace Gtk;</b> (which is not recommendedpractice for Gtk--, so it is not a problem). Additionally, the<b>using</b>-declarations are wrapped in macros thatare set based on autoconf-tests to either "" or i.e. <b>usingstd::string;</b> (depending on whether the system haslibstdc++ 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> beforeusing it, you avoid getting errors on systems where no part of thelibrary 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>usingstd::string;</b>, and if the "hack" for gtk-- mentioned abovedoes not work, then I see two solutions:<div class="itemizedlist"><ul type="disc"><li><p>Define <b>std::</b> as a macro if the compilerdoesn't know about <b>std::</b>.<pre class="programlisting">#ifdef OLD_COMPILER#define std#endif</pre>(thanks to Juergen Heinzl who posted this solution ongnu.gcc.help)</p></li><li><p>Define a macro NS_STD, which is defined toeither "" 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") onsystems 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 dealwith this</h3></div></div><p>This information was gathered around May 2000. It may not be correctby 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 someusing-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 allnamespace-handling in macros to support compilers withoutnamespace-support (no libstdc++ used in headers)</td></tr></tbody></table></div><p>As you can see, this currently lacks an example of a projectwhich uses libstdc++-symbols in headers in a back-portable way(except for Gtk--: see the <a href="#sec-gtkmm-hack" title="Using namespacecomposition if the project uses a separatenamespace">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::noreplacein ISO 14882</h2></div></div><p>I have seen <b>ios::nocreate</b> being used forinput-streams, most probably because the author thought it would bemore correct to specify nocreate "explicitly". So you can simplyleave it out for input-streams.</p><p>For output streams, "nocreate" is probably the default, unless youspecify <b>std::ios::trunc</b> ? To be safe, you can openthe file for reading, check if it has been opened, and then decidewhether you want to create/replace or not. To my knowledge, evenolder 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(intfd)</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 filedescriptors. Of those that do, not all of them use integers to representthem.</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, andit 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 usefiledescriptors), you need to implement a subclass of<b>std::streambuf</b> (or<b>std::basic_streambuf<..></b>) which opens a filegiven a descriptor, and then pass an instance of this to thestream-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 generatesa 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-levelheaders) from C++ programs. Instead, you should use a set ofheaders that are named by prepending 'c' and, as usual,omitting the extension (.h). For example, instead of using<tt><math.h></tt>, youshould use <tt><cmath></tt>. In some cases this hasthe advantage that the C++-header is more standardized thanthe 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> inthis case), the symbols will be available both in the globalnamespace and in namespace <b>std::</b> (butlibstdc++ does not yet have fully compliant headers) On theother hand, if you include only the new header (i.e. <tt><cmath></tt>), the symbolswill 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 theGNU C++ implementation might reuse ("shadow") the Clibrary-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> doesnot 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. Becauseof 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 workingfixes for existing uses of iterators.<div class="itemizedlist"><ul type="disc"><li><p>you cannot do<b>ostream::operator<<(iterator)</b> toprint 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 anymore => 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 aboutc-headers</a>.</p><p>Older implementations of libstdc++ (g++-2 for egcs 1.x and g++-3for gcc 2.95.x), however, keep these functions as macros, and so itis 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 usingautoconf-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 aheader-file so that g++-2 (egcs 1.x) and g++-3 (gcc 2.95.x) define amacro which tells <tt><ctype.h></tt> to define functionsinstead 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 namespacestd;</b> declaration at the top, and include <tt><ctype.h></tt>. This will result inambiguities between the definitions in the global namespace(<tt><ctype.h></tt>) and thedefinitions in namespace <b>std::</b>(<b><cctype></b>).</p><p>The solution to this problem was posted to the libstdc++-v3mailing-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, shadowheaders are not being searched....’This is now outdated, but gcc 3.0 still does not have fullycompliant "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 ideato 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 latterreturns the string).<pre class="programlisting">voidclear() { _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 morecomplicated (from libstdc++-v3), but <b>clear</b> is notimplemented 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 compatibilitywith 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 bedeprecated</p></li><li><p> <b>strstream</b> is limited to<b>char</b></p></li><li><p> with <b>ostringstream</b> you don'thave to take care of terminating the string or freeing itsmemory</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_SSTREAMstd::ostringstream oss;#elsestd::ostrstream oss;#endifoss << "Name=" << m_name << ", number=" << m_number << std::endl;...#ifndef HAVE_SSTREAMoss << 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 yoursm_label.set_text(oss.str());#ifndef HAVE_SSTREAM// let the ostrstream take care of freeing the memoryoss.freeze(false);#endif</pre></p><p>Input-stringstreams can be used similarly:<pre class="programlisting">std::string input;...#ifdef HAVE_SSTREAMstd::istringstream iss(input);#elsestd::istrstream iss(input.c_str());#endifint 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 istrstreamiss.clear();iss.str(denominator);iss >> m_den;</pre>If you don't care about speed, you can put these conversions ina template-function:<pre class="programlisting">template <class X>void fromString(const string& input, X& any){#ifdef HAVE_SSTREAMstd::istringstream iss(input);#elsestd::istrstream iss(input.c_str());#endifX 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 informationcomes from there. Additionally, there is information in"info iostream", which covers the old implementation that gcc 2.95.xuses.</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 fordiscussion to the libstdc++-v3-mailing-list.</p></div></div></body></html>