<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>Creating and Using Streams Instantiated on User-Defined Types</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="41-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="42.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library User's Guide</B></DIV>
<H2>41.3 Creating and Using Streams Instantiated on User-Defined Types</H2>
<A NAME="idx971"><!></A>
<P>Once all the support work is finished, you can instantiate a stream class template on your type and begin to use it--well, not quite. Because the new stream requires the new facets you've defined, you must first create a new locale containing these facets and then imbue that locale on your stream. You can do this as follows:</P>

<UL><PRE>
typedef std::basic_fstream&lt;Echar,Etraits&gt; Estream;           // 1
std::locale Eloc(std::locale(std::locale(),
                             new Ecodecvt),new Ectype);      // 2
Estream foo("foo.txt");                                      // 3
foo.imbue(Eloc);                                             // 4
</PRE></UL>
<TABLE CELLPADDING="3">

<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>Typedef the special stream type to something convenient.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>Construct a new locale object and replace the <SAMP>std::codecvt</SAMP> and <SAMP>std::ctype</SAMP> facets with the ones we've defined for <SAMP>Echar</SAMP>. We use the constructor that takes an existing locale and a new facet to construct a locale with a new <SAMP>codecvt</SAMP> facet, and then use it again to get a <SAMP>locale</SAMP> with both new facets.
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>Construct an <SAMP>Estream</SAMP>.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>Imbue the new <SAMP>locale</SAMP> object containing our replacement facets onto the <SAMP>Estream</SAMP>.
</TABLE>
<P>Now we're ready to insert <SAMP>Echar</SAMP>s into the stream and read them back in:</P>

<UL><PRE>
Echar e[10];
Estream::pos_type pos = foo.tellp();                           //1
foo &lt;&lt; 10;                                                     //2
foo.seekg(pos);                                                //3
foo &gt;&gt; e;                                                      //4
</PRE></UL>
<TABLE CELLPADDING="3">

<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>Get current position.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>Write out the integer <SAMP>10</SAMP>.
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>Seek back.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>Read in the string <SAMP>10</SAMP> as <SAMP>Echar</SAMP>s. 
</TABLE>

<BR>
<HR>
<A HREF="41-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="42.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
