<!--
    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>Patterns for Extractors and Inserters of User-Defined Types</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="32-5.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="33.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>32.6 Patterns for Extractors and Inserters of User-Defined Types</H2>
<A NAME="idx796"><!></A>
<P>Here is the pattern for an extractor:</P>

<UL><PRE>
template&lt;class charT, class Traits&gt;
std::basic_istream&lt;charT, Traits&gt;&amp; 
operator&gt;&gt; (std::basic_istream&lt;charT,
            Traits&gt;&amp; is, UserDefinedType&amp; x)
{
  std::ios_base::iostate err = 0;

  // Create a sentry object (may set error bits or throw failure)
  typename basic_istream&lt;charT, Traits&gt;::sentry ipfx(is);

  try {

    // Proceed with I/O only if sentry is okay.

    if(ipfx) {
      // Typically you access the stream's locale or buffer.
      // Don't call other stream I/O functions.

      // Add state bits to the err variable if necessary,
      // for example:
      // if (...) 
      //    err |= std::ios_base::failbit;
    }
  }
  catch(...) {
    bool flag = false;
    try { 
      // set failbit (may throw failure)
      is.setstate(std::ios_base::failbit);
    }
    catch(...) { flag = true; }

    // Re-throw original exception (thrown from facet or buffer)
    if (flag)
      throw;
  }

  // As the last step, set error bits (may throw failure)
  if (err)
    is.setstate(err);

  return is;
}
</PRE></UL>
<A NAME="idx797"><!></A>
<P>Similarly, the pattern for the inserter looks like this:</P>

<UL><PRE>
template&lt;class charT, class Traits&gt;
std::basic_ostream&lt;charT, Traits&gt;&amp;
operator&lt;&lt;(std::basic_ostream&lt;charT, Traits &gt;&amp; os,
            const UserDefinedType&amp; x)
{
  std::ios_base::iostate err = 0;

  // Create a sentry object (may set error bits or throw failure)
  typename basic_ostream&lt;charT, Traits&gt;::sentry opfx(os);

  try {
    // Proceed with I/O only if sentry is okay
    if (opfx) {
      // Typically you access the stream's locale or buffer.
      // Don't call other stream I/O functions

      // Add state bits to the err variable if necessary,
      // for example:
      // if (...) 
      //    err |= std::ios_base::failbit;

      // Reset the field width after usage, that is,
      // os.width(0);
    }
  } //try
  catch(...) {
    bool flag = false;
    try { 
      // set failbit (may throw failure)
      os.setstate(std::ios_base::failbit);
    }
    catch(...) {
      // Catch exception, do not rethrow
      flag = true;
    }
    // Rethrow original exception (from facet or buffer)
    if (flag)
       throw;
  }

  // As the last step, set error bits (may throw failure)
  if (err)
    os.setstate(err);
 
  return os;
}
</PRE></UL>

<BR>
<HR>
<A HREF="32-5.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="33.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>
