    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: An Introduction to FastFormat (Part 3): Solving Real Problems, Quickly</title>
        <link>https://members.accu.org/index.php/articles/1561</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Design of applications and programs + Overload Journal #91 - June 2009</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c67/">Design</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c253/">91</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-67-253/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+67+253/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;An Introduction to FastFormat (Part 3): Solving Real Problems, Quickly</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 10 June 2009 09:56:00 +01:00 or Wed, 10 June 2009 09:56:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;A good library must be useful in practice. Matthew Wilson looks at usability and extendability.</p>
<p><strong>Body:</strong>&nbsp;<p>This article, the third and last of the current series on the FastFormat formatting library, discusses several use cases, from real world projects and discussion forums, that illustrate how the library can be used to achieve concise, transparent application code while utilising its flexibility and performance advantages. It is about solving real formatting problems, quickly: both in speed of development and speed of executed code.
  </p><p> 
    Along the way, we'll look at some of the more esoteric aspects of the application layer, customisation of the format specification defect handling, and consider cases where suppressing unused argument exceptions is useful.
  </p><h2>
    Introduction
  </h2><p> 
    This article is divided into two halves. The first half describes six use cases, four of which are from real applications, four of which demonstrate improvements to application code, and four of which involve performance benefits. (Not the same four.) I'll present performance measures for each scenario for which it is relevant, putting more flesh on the performance characteristics suggested in the Yaffle scenario from part 1 [<a href="#FF1">FF1</a>]
				. The second half of the article is a mix of miscellaneous but useful tips for taking your use of the library further. Along the way we'll see examples of FastFormat interoperability with MFC, ATL, and the Pantheios logging library 
				      [<a href="#PAN">PAN</a>]
				.
  </p><p> 
    The first two scenarios are pedagogical, contrasting the use of FastFormat for formatting columnar floating-point data, and in formatting according to absolute tabulations. The benefit of using FastFormat in these cases is primarily in performance.
  </p><p> 
    The next two are extracts from client codebases, and involve server connection logging and database insert statement preparation. These demonstrate improvements both in application code transparency and performance.
  </p><p> 
    The last two scenarios do not involve performance improvements. (Well, they might, but that's unimportant.) Rather, they involve substantial improvements in the transparency of application code by dint of FastFormat's expressiveness and flexibility.
  </p><h3>
    FastFormat in action
  </h3><p> 
    Several of the scenarios described here are extracted from clients' work, and so names have been changed and types simplified. Also, the samples assume the inclusion of the fastformat/ff.hpp header to alias the <tt class="code">fastformat</tt> namespace to <tt class="code">ff</tt>, and the inclusion of whatever other headers are required for the various types and libraries involved. The full source of all the programs are included with the FastFormat distribution (version 0.4+).
  </p><p> 
    Except where stated otherwise, the performance of each scenario was ascertained by invoking each of the statements 10,000 times, and repeating that loop three times, taking the times on the third outer iteration to minimise environment effects (since we're writing to <tt class="code">stdout</tt>). The output was piped to a bit-bucket program - just a <tt class="code">getchar()</tt> loop - to remove the latency of writing to the console/terminal from the measured times. The results are presented in milliseconds. The tests were conducted on Mac OS-X with GCC 4.0 (32-bit), on Linux with GCC 4.1 (64-bit), and on Windows with Visual C++ 9 (32-bit).
  </p><h3>
    Floating-point columns
  </h3><p> 
    The first scenario is based on a question about C++ formatting on StackOverflow 
				      [<a href="#SO">SO</a>]
				, which asked how to do the following using the IOStreams:
  </p>
<pre class="programlisting">
      printf(&quot;%-14.3f%-14.3f\n&quot;, 12345.12345,  
      12345.12345);  
</pre><p> 
    resulting in the output (where &sdot; represents a space):
  </p>
<pre class="programlisting">
      12345.123&sdot;&sdot;&sdot;&sdot;&sdot;12345.123&sdot;&sdot;&sdot;&sdot;&sdot;  
</pre><p> 
    The implementations for IOStreams, Boost.Format, and FastFormat are shown in Listing 1. Note that I've added enclosing square braces as an aid to verifying that they all produce identical output. (This was done simply by running them all through <tt class="code">uniq</tt>, a little trick I learned from a UNIX guru long ago.)
  </p>
  <p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    // Streams  
    printf(  
      &quot;[%-14.3f%-14.3f]\n&quot;  
    , 12345.12345  
    , 12345.12345  
    );  
 
    // IOStreams  
    std::cout   
      &lt;&lt; '['  
      &lt;&lt; std::setiosflags(std::ios::fixed)  
      &lt;&lt; std::left  
      &lt;&lt; std::setprecision(3)  
      &lt;&lt; std::setw(14)  
      &lt;&lt; 12345.12345  
      &lt;&lt; std::setw(14)  
      &lt;&lt; 12345.12345  
      &lt;&lt; ']'  
      &lt;&lt; std::endl;  
 
    // FastFormat.Format  
    ff::fmtln(  
      std::cout  
    , &quot;[{0}{1}]&quot;  
    , ff::to_f(12345.12345, -14, 3)  
    , ff::to_f(12345.12345, -14, 3)  
    );  
 
    // Boost.Format  
    std::cout  
      &lt;&lt; boost::format(&quot;[%-14.3f%-14.3f]\n&quot;)  
        % 12345.12345  
        % 12345.12345;  
</pre>
</td></tr><tr><td class="title">Listing 1</td></tr></table>
  </p>
<p> 
    All present clear and transparent code except, in my opinion, the IOStreams, due to the verbosity of the code and the inconsistent semantics between the manipulators <tt class="code">setprecision</tt> (sticky) and <tt class="code">setw</tt> (non-sticky). Of course, some may argue that the explicit nature of something like <tt class="code">setprecision</tt> is far more transparent than an arcane squiggle such as <tt class="code">&quot;%-14.3f&quot;</tt>. So the issue of transparency here is somewhat subjective.
  </p><p> 
    Totally objective, however, are the performance results, in milliseconds, are shown in Table 1. It's no big surprise to see that Streams is the standout performer here (since all the others form their floating-point arguments in terms of <tt class="code">sprintf()</tt>).</p>
<table class="sidebartable"><tr><td>
<p>
Times (in ms) for 10,000 invocations of the Floating-Point 
Columns scenario
</p>
<p>
<table border="1"><tr><th>Library</th><th>GCC 4.0 (32)</th><th>GCC 4.1 (64)</th><th>VC++ 9 (32)</th></tr>
<tr><td>Streams</td><td>14.7</td><td>33.5</td><td>43.9</td></tr>
<tr><td>IOStreams</td><td>81.1</td><td>91.8</td><td>152.2</td></tr>
<tr><td>Boost.Format</td><td>103.3</td><td>104.0</td><td>223.8</td></tr>
<tr><td>FastFormat.Format</td><td>21.6</td><td>42.5</td><td>64.7</td></tr>
<tr><td>Boost.Format (1-arg)</td><td>109.7</td><td>105.6</td><td>224.9</td></tr>
<tr><td>FastFormat.Format (1-arg)</td><td>13.4</td><td>27.2</td><td>38.9</td></tr>
</table>
</p>
</td></tr><tr><td class="title">Table 1</td></tr>
</table>    
    <p> 
    Since <tt class="code">Boost.Format</tt> and <tt class="code">FastFormat.Format</tt> both allow an argument to be reused, we can simplify the statements and just have one argument, as in Listing 2 (floating-point column solutions reusing a single parameter). While there's little realism for the current scenario, there are cases where it is useful to use arguments multiple times, so it's interesting to see the effect. The times are shown in the bottom two rows of Table 1.
  </p>

<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    // FastFormat.Format  
    ff::fmtln(  
      std::cout  
    , &quot;[{0}{0}]&quot;  
    , ff::to_f(12345.12345, -14, 3)  
    );  
 
    // Boost.Format  
    std::cout  
      &lt;&lt; boost::format(&quot;[%1$-14.3f%1$-14.3f]\n&quot;)  
        % 12345.12345;  
</pre>
</td></tr><tr><td class="title">Listing 2</td></tr></table>
  </p><p> 
    As expected, FastFormat's time drops, making it even faster than Streams for this edge case. The <tt class="code">Boost.Format</tt> times stay almost exactly the same, so we may assume that it must perform the argument conversion twice.
  </p><h3>
    Tabulations
  </h3><p> 
    One of <tt class="code">Boost.Format</tt>'s advanced features is the ability to apply absolute tabulations, something none of the other examined libraries is able to do. The example given on the library's website, assumes three vectors of strings, such that when used with the following statement 
  </p>
<pre class="programlisting">
      std::cout   
        &lt;&lt; boost::format(&quot;%1%, %2%, %|30t|%3%\n&quot;)  
          % forenames[i]  
          % surnames[i]  
          % tels[i];  
</pre><p> 
    the output is as follows:
  </p>
<pre class="programlisting">
      Marc-Fran&ccedil;ois Michel, Durand, 0123 456 789  
      Jean, de Lattre de Tassigny,  0987 654 321  
</pre><p> 
    As I mentioned in part 1 
				      [<a href="#FF1">FF1</a>
				], FastFormat is able to support absolute tabulations with a little indirection. The above output can be obtained as shown in Listing 3 (synthesising absolute tabluations with <tt class="code">FastFormat.Format</tt>)..
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    std::string scratch;  
 
    ff::fmtln(  
      std::cout  
    , &quot;{0,40,,&lt;}{1}&quot;  
    , ff::fmt(  
        scratch  
      , &quot;{0}, {1}, &quot;  
      , forenames[i]  
      , surnames[i]  
      )  
    , tels[i]  
    );  
</pre>
</td></tr><tr><td class="title">Listing 3</td></tr></table>
  </p><p> 
    Clearly it's not as transparent as the <tt class="code">Boost.Format</tt> statement, but it's not opaque either. And given the relative performances (Table 2), the picture's not too bad.</p>
<table class="sidebartable"><tr><td>
<p>
Times (in ms) for 10,000 invocations of the Tabulations 
scenario
</p>
<p>
<table border="1"><tr><th>Library</th><th>GCC 4.0 (32)</th><th>GCC 4.1 (64)</th><th>VC++ 9 (32)</th></tr>
<tr><td>Boost.Format</td><td>237.2</td><td>141.8</td><td>366.8</td></tr>
<tr><td>FastFormat.Format</td><td>37.0</td><td>46.0</td><td>149.1</td></tr>
</table>
</p>
</td></tr><tr><td class="title">Table 2</td></tr>
</table>    
    <h3>
    Server connection Log
  </h3><p> 
    This next scenario is extracted from a client's proprietary internetworking server (UNIX and Windows), which writes out connection event logs containing connection identifier, addresses + port, time and bytes transferred. Consider the following fictionalised structure:
  </p>
<pre class="programlisting">
      struct connection_t  
      {  
        std::string     connectionId;  
        struct in_addr  remoteAddress;  
        struct in_addr  localAddress;  
        unsigned short  port;  
        unsigned long   numBytesTransferred;  
        struct tm       completionTime;  
      } conn;  
 
      conn.remoteAddress.s_addr = htonl(0xC0A8A0f7);  
      conn.localAddress.s_addr  = htonl(0x7f000001);  
      conn.port                 = 5651;  
      conn.numBytesTransferred  = 102401;  
      conn.completionTime       = . . . // now
      conn.connectionId         = &quot;channel-1&quot;;  
</pre><p> 
    Currently, the format of the log is (though this may change):
  </p>
<pre class="programlisting">
      &lt;id&gt; &lt;time&gt; &lt;remote-addr&gt; &lt;local-addr&gt; &lt;port&gt;  
      &lt;bytes&gt;  
</pre><p> 
    giving an output along the lines of:
  </p>
<pre class="programlisting">
      channel-1 May 03 03:50:41 2009 192.168.160.247  
      127.0.0.1 5651 102401  
</pre><p> 
    This can be achieved simply with both FastFormat APIs, as shown in Listings 4 and 5. In this case I think the <tt class="code">FastFormat.Format</tt> version is more transparent, and makes reordering of the replacement parameters a trivial matter (as suggested by the non-sequential format string in the example).
  </p>
		<ul><li> 
    Listing 4 shows a <tt class="code">FastFormat.Write</tt> implementation of the Server Connection Log scenario
  </li></ul>

<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    void log_connection(connection_t const&amp; conn)  
    {  
      ff::writeln(  
        stm  
      , conn.connectionId  
      , &quot; &quot;  
      , conn.completionTime  
      , &quot; &quot;  
      , conn.remoteAddress  
      , &quot; &quot;  
      , conn.localAddress  
      , &quot; &quot;  
      , conn.port  
      , &quot; &quot;  
      , conn.numBytesTransferred  
      );  
    }  
</pre>
</td></tr><tr><td class="title">Listing 4</td></tr></table>
  </p>
		<ul><li> 
    Listing 5 shows a <tt class="code">FastFormat.Format</tt> implementation of the Server Connection Log scenario
  </li></ul>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    void log_connection(connection_t const&amp; conn)  
    {  
      ff::fmtln(  
        std::cout  
      , &quot;{0} {5} {1} {2} {3} {4}&quot;  
      , conn.connectionId  
      , conn.remoteAddress  
      , conn.localAddress  
      , conn.port  
      , conn.numBytesTransferred  
      , conn.completionTime  
      );  
    }  
</pre>
</td></tr><tr><td class="title">Listing 5</td></tr></table>
  </p><p> 
    With Streams, IOStreams or any other library that does not support the automatic insertion of <tt class="code">struct in_addr</tt> and <tt class="code">struct tm</tt>, providing equivalent functionality is going to involve extra effort. Consider the Streams version (Listing 6), which is pretty close to the original implementation. There's considerably more code, and it's clear why the log format was originally difficult to change.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    void log_connection(connection_t const&amp; conn)  
    {  
      char    time[21];  
      size_t  n0 = strftime(  
          &amp;time[0], STLSOFT_NUM_ELEMENTS(time)  
        , &quot;%b %d %H:%M:%S %Y&quot;  
        , &amp;conn.completionTime);  
      STLSOFT_ASSERT(  
         n0 &lt; STLSOFT_NUM_ELEMENTS(time));  
 
      uint32_t ra_l =  
         ntohl(conn.remoteAddress.s_addr);  
      uint32_t la_l =  
        ntohl(conn.localAddress.s_addr);  
 
      fprintf(  
        stdout  
      , &quot;%.*s %.*s %d.%d.%d.%d %d.%d.%d.%d %d %lu\n&quot;  
      , int(conn.connectionId.size())  
          , conn.connectionId.data()  
      , int(n0), time  
      , ((ra_l &gt;&gt; 24) &amp; 0xff),  
        ((ra_l &gt;&gt; 16) &amp; 0xff),  
        ((ra_l &gt;&gt;  8) &amp; 0xff),  
        ((ra_l &gt;&gt;  0) &amp; 0xff)  
      , ((la_l &gt;&gt; 24) &amp; 0xff),  
        ((la_l &gt;&gt; 16) &amp; 0xff),  
        ((la_l &gt;&gt;  8) &amp; 0xff),  
        ((la_l &gt;&gt;  0) &amp; 0xff)  
      , conn.port  
      , conn.numBytesTransferred  
      );  
    }  
</pre>
</td></tr><tr><td class="title">Listing 6</td></tr></table>
  </p><p> 
    The brittleness of the Streams example format string can be obviated by using IOStreams, although it does require the definition of two inserters (Listing 7: IOStream Inserters for <tt class="code">struct tm</tt> and <tt class="code">struct in_addr</tt>) in order to cut down on the amount of application code.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    inline std::ostream&amp; operator &lt;&lt;(  
      std::ostream&amp;     stm  
    , struct tm const&amp;  t  
    )  
    {  
      char    time[21];  
      size_t  n0 = strftime(  
          &amp;time[0], STLSOFT_NUM_ELEMENTS(time)  
        , &quot;%b %d %H:%M:%S %Y&quot;  
        , &amp;t);  
      STLSOFT_ASSERT(n0 &lt;  
         STLSOFT_NUM_ELEMENTS(time));  
      return stm.write(time, n0);  
    }  
 
    inline std::ostream&amp; operator &lt;&lt;(  
      std::ostream&amp;         stm  
    , struct in_addr const&amp; addr  
    )  
    {  
      uint32_t ra = ntohl(addr.s_addr);  
 
      return stm  
          &lt;&lt; ((ra &gt;&gt; 24) &amp; 0xff)  
          &lt;&lt; '.'   
          &lt;&lt; ((ra &gt;&gt; 16) &amp; 0xff)   
          &lt;&lt; '.'  
          &lt;&lt; ((ra &gt;&gt; 8) &amp; 0xff)   
          &lt;&lt; '.'  
          &lt;&lt; ((ra &gt;&gt; 0) &amp; 0xff);  
    }  
</pre>
</td></tr><tr><td class="title">Listing 7</td></tr></table>
  </p><p> 
    With these, we can now write a much improved version using IOStreams (Listing 8).
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    void log_connection(connection_t const&amp; conn)  
    {  
      std::cout  
        &lt;&lt; conn.connectionId  
        &lt;&lt; ' '  
        &lt;&lt; conn.connectionTime  
        &lt;&lt; ' '  
        &lt;&lt; conn.remoteAddress  
        &lt;&lt; ' '  
        &lt;&lt; conn.localAddress  
        &lt;&lt; ' '  
        &lt;&lt; conn.port  
        &lt;&lt; ' '  
        &lt;&lt; conn.numBytesTransferred  
        &lt;&lt; std::endl;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 8</td></tr></table>
  </p><p> 
    It's worth noting that the compatibility for <tt class="code">struct tm</tt> and <tt class="code">struct in_addr</tt> that is afforded to FastFormat (and other libraries, such as Pantheios 
				      [<a href="#PAN">PAN</a>]
				) by STLSoft's string access shims (see 
				      [<a href="#FF2">FF2</a>]
				, 
				      [<a href="#XSTLv1">XSTLv1</a>]
				, 
				      [<a href="#IC++">IC++</a>]
				for more details) is automatic. You don't have to define anything to make use of it, merely ensure the right <tt class="code">#include</tt>s are made. This is a clear win for FastFormat over IOStreams in the case of <tt class="code">struct in_addr</tt>, since the dotted-decimal format (e.g. 127.0.0.1) is widely accepted. However, with <tt class="code">struct tm</tt>, it is only convenient by accident, since the string access shim format - a l&agrave; <tt class="code">strftime()</tt> -  is equivalent to that required by the server log. If any other format was required, then you'd either have to write an inserter function or customise via the <tt class="code">filter_type</tt> mechanism (see 
				      [<a href="#FF2">FF2</a>]
				), each of which is equivalent to the effort of defining an inserter.
  </p><p> 
    The relative performances are shown in Table 3. It's no surprise that the IOStreams solution fairs poorly, but it is interesting to see how FastFormat (in either guise) is on a par, or even better in some cases, than Streams in a non-trivial real-world example. Given the substantial differences in transparency of the code, FastFormat would appear to be a clear winner in this case.</p>

<table class="sidebartable"><tr><td>
<p>
Times (in ms) for 10,000 invocations of the Tabulations 
scenario
</p>
<p>
<table border="1"><tr><th>Library</th><th>GCC 4.0 (32)</th><th>GCC 4.1 (64)</th><th>VC++ 9 (32)</th></tr>
<tr><td>Streams</td><td>53.0</td><td>59.5</td><td>86.6</td></tr>
<tr><td>IOStreams</td><td>94.4</td><td>111.3</td><td>248.5</td></tr>
<tr><td>FastFormat.Format</td><td>56.0</td><td>55.0</td><td>86.7</td></tr>
<tr><td>FastFormat.Write</td><td>49.7</td><td>47.8</td><td>86.5</td></tr>
</table>
</p>
</td></tr><tr><td class="title">Table 3</td></tr>
</table>

    <h3>
    Database insert statement
  </h3><p> 
    This next scenario is from a client's (UNIX) codebase. The particular code is to form a database insert statement, part of a high volume data processing subsystem. The client does, er, financial things, and they're extremely cagey about their work, so I hope you'll forgive the heavy obfuscation of names and types.
  </p><p> 
    The original implementation was done using <tt class="code">std::stringstream</tt> to form the statement, along the lines shown in Listing 9.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    const int   intNaN = 0x7fffffff;  
 
    class BusinessAdaptor  
    {  
      . . .  
    public:  
      std::string         m_tablename;  
      int                 m_id_1;  
      std::stringstream   m_ss;  
      std::stringstream   m_slice;  
    };  
 
    std::string BusinessAdapter::insertRecord(  
      const BusinessRecord&amp; r  
    )  
    {  
      m_ss.str(&quot;&quot;);  
      m_ss &lt;&lt; &quot;insert[&quot; &lt;&lt; m_tablename &lt;&lt; &quot;;(&quot;;  
      m_ss &lt;&lt; makeSlice(r.member_1)    &lt;&lt; &quot;;&quot;;  
      m_ss &lt;&lt; makeSlice(r.member_2)    &lt;&lt; &quot;;&quot;;  
      m_ss &lt;&lt; makeSlice(r.member_3)    &lt;&lt; &quot;;&quot;;  
      m_ss &lt;&lt; makeSlice(r.member_4)    &lt;&lt; &quot;;&quot;;  
      m_ss &lt;&lt; makeSlice(m_id_1)        &lt;&lt; &quot;;&quot;;  
      m_ss &lt;&lt; makeSlice(r.member_5)    &lt;&lt; &quot;;&quot;;  
      . . . // same for members 6 =&gt; 18  
      m_ss &lt;&lt; makeSlice(r.member_19)   &lt;&lt; &quot;)]&quot;;  
      return m_ss.str();  
    }  
</pre>
</td></tr><tr><td class="title">Listing 9</td></tr></table>
  </p><p> 
    The <tt class="code">member_??</tt> variables are all integers. The <tt class="code">makeSlice()</tt> helper function converts an integer to a string except where it is equal to the application-defined sentinel constant <tt class="code">intNan</tt>, in which case it is converted to the string <tt class="code">&quot;0N&quot;</tt>, as in:
  </p>
<pre class="programlisting">
      std::string BusinessAdapter::makeSlice(  
        const int val)  
      {  
        m_slice.str(&quot;&quot;);  
        if ( val == intNaN )  
          m_slice &lt;&lt; &quot;0N&quot;;  
        else  
          m_slice &lt;&lt; val;  
        return m_slice.str();  
      }  
 
</pre><p> 
    The client is a heavy (and happy) user of a customised version of Pantheios 
				      [<a href="#PAN">PAN</a>]
				, and wished to know whether there were similar performance gains to be had in a more general way in the manipulation of strings. This was at a time before FastFormat had been released (and this was a primary impetus to my getting it out there), and I was able to show them the performance speed-up shown in Table 4; in this case the times are measured in microseconds for 10,000 invocations (since there's no I/O).</p>

<table class="sidebartable"><tr><td>
<p>

Times (in &micro;s) for 10,000 invocations of the Database Insert 
Statement scenario
</p>
<p>
<table border="1"><tr><th>Library</th><th>GCC 4.0 (32)</th><th>GCC 4.1 (64)</th><th>VC++ 9 (32)</th></tr>
<tr><td>IOStreams</td><td>1210</td><td>1546</td><td>5378</td></tr>
<tr><td>FastFormat.Format</td><td>533</td><td>456</td><td>569</td></tr>
<tr><td>FastFormat.Write</td><td>468</td><td>396</td><td>530</td></tr>
</table>
</p>
</td></tr><tr><td class="title">Table 4</td></tr>
</table>				
				
				<p> 
    The two FastFormat implementations are shown in Listings 10 and 11. Neither can be said to be significantly more transparent than the original. Actually, in this case I'd concede that <tt class="code">FastFormat.Format</tt> is less transparent, simply because having 21 replacement parameters in a format string is a challenge to maintenance. None of the solutions are easy on the eye, probably because a string is being built from 21 arguments. The primary discriminant in this case is performance. I would observe that at least the FastFormat.Format version has an extra level of error-checking over the other two, since if there are too many or too few arguments, an exception will be thrown.
  </p>
		<ul><li> 
    Listing 10 shows a <tt class="code">FastFormat.Format</tt> implementation of the Database Inserter Statement scenario
  </li></ul>

<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    std::string BusinessAdapter::insertRecord(  
      const BusinessRecord&amp; r  
    )  
    {  
      std::string result;  
      ff::fmt(  
        result  
      ,   &quot;insert[{0};({1};{2};{3};{4};{5};{6};{7};{8};{9};
      {10};{11};{12};{13};{14};{15};{16};{17};{18};{19};
      {20})]&quot;  
      ,   m_tablename  
      ,   make_slice(r.member_1)  
      ,   make_slice(r.member_2)  
      ,   make_slice(r.member_3)  
      ,   make_slice(r.member_4)  
      ,   make_slice(m_id_1)  
      ,   make_slice(r.member_5)  
      . . . // same for members 6 =&gt; 18  
      ,   make_slice(r.member_19)  
      );  
      return result;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 10</td></tr></table>
  </p>
		<ul><li> 
    Listing 11 shows a <tt class="code">FastFormat.Write</tt> implementation of the Database Inserter Statement scenario
  </li></ul><p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    std::string BusinessAdapter::insertRecord(  
      const BusinessRecord&amp; r  
    )  
    {  
      std::string result;  
      ff::write(  
          result  
      ,   &quot;insert[&quot;,  m_tablename  
      ,   &quot;;(&quot;,       make_slice(r.member_1)  
      ,   &quot;;&quot;,        make_slice(r.member_2)  
      ,   &quot;;&quot;,        make_slice(r.member_3)  
      ,   &quot;;&quot;,        make_slice(r.member_4)  
      ,   &quot;;&quot;,        make_slice(m_id_1)  
      ,   &quot;;&quot;,        make_slice(r.member_5)  
      . . . // same for members 6 =&gt; 18  
      ,   &quot;;&quot;,        make_slice(r.member_19)  
      ,   &quot;)]&quot;  
      );  
      return result;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 11</td></tr></table>
  </p>
<p> 
    Readers of part 2 
				      [<a href="#FF2">FF2</a>]
				 should recognise aspects of the implementation of the <tt class="code">make_slice()</tt> inserter function (Listing 12), which provides equivalent semantics to the original <tt class="code">makeSlice()</tt> but uses shim strings 
				      [<a href="#STLv">STLv</a>]
				, 
				      [<a href="#FF1">FF1</a>]
				 to avoid memory allocations, and to reuse the existing FastFormat integer-to-string conversions.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    stlsoft::basic_shim_string&lt;char, 20&gt;  
      make_slice(const int val)  
    {  
      if(intNaN == val)  
      {  
        return stlsoft::basic_shim_string&lt;char,  
           20&gt;(&quot;0N&quot;);  
      }  
      else  
      {  
        return fastformat::filters::filter_type(val,  
           &amp;val, static_cast&lt;char const*&gt;(0));  
      }  
    }  
</pre>
</td></tr><tr><td class="title">Listing 12</td></tr></table>
  </p><h3>
    CComBSTR, std::string, std::wstring and CString
  </h3><p> 
    This example is heavily edited from a client's codebase. Please don't try to understand the functions' original purposes, just focus on the formulation of the result string. Listing 13 shows the old version of <tt class="code">GetFilter()</tt> (along with some other things, representative of the original code, that are required just to get the snippet to compile)
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    #define atFilter            1  
    #define strFilterSeparator  L&quot;-&quot;  
    enum dimension_t;  
    HRESULT XXGetFilterEx_(  
      dimension_t dimension  
    , int newIndex  
    , std::string* fg  
    , std::string* fv  
    ); // Assign to *fg and *fv
    int offset_to_new_index_(  
      int filter  
    , dimension_t dimension  
    , int index  
    ); // calc index, e.g. 'return index + 1;'
    HRESULT GetFilter(  
      dimension_t dimension  
    , short index  
    , BSTR* filter  
    )  
    {  
      std::string  szFG;  
      std::string  szFV;  
      int  newIndex  = offset_to_new_index_(  
         atFilter, dimension, index);  
      XXGetFilterEx_(dimension, newIndex,  
         &amp;szFG, &amp;szFV);  
      CString flt(szFG.c_str());  // +1
      flt += strFilterSeparator;  // +2
      flt += szFV.c_str();        // +1
      CComBSTR filter(flt);       // +1
      *filter = filter.Detach();  
      return S_OK;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 13</td></tr></table>
  </p><p> 
    The comments indicate the number of memory allocations, involved in a typical invocation. The type transitions in this case are <tt class="code">std::string</tt> -&gt; <tt class="code">CString</tt> (x2), <tt class="code">wchar_t const*</tt> -&gt; <tt class="code">CString</tt>, and <tt class="code">CString </tt>-&gt; <tt class="code">CComBSTR</tt>. Listing 14 shows the new version of <tt class="code">GetFilter() </tt>that is implemented in terms of <tt class="code">FastFormat.Write</tt>, using the sink for <tt class="code">CComBSTR</tt>.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    HRESULT GetFilter(dimension_t dimension, 
                      short index, BSTR* filter)  
    {  
      . . . // as before  
      CComBSTR filter;  
      *filter = fastformat::write(  
        filter  
      , szFG  
      , winstl::w2m(strFilterSeparator)  
      , szFV  
      ).Detach(); // +1
      return S_OK;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 14</td></tr></table>
  </p><p> 
    As you can see, the original five statements have been reduced to two, and the number of memory allocations have been reduced from five to one. Were it not for the need to compress the main statement into the narrow display confines of this magazine, it would be evident that it's also more transparent than the original. There's no performance test for this case - the main aim in the change was to increase transparency and maintainability, and aiding in the project-wide task of removing dependency on the MFC library (incl. <tt class="code">CString</tt>).
  </p><h3>
    MessageBox
  </h3><p> 
    This last example, another extract from a commercial project, is also about improvements to transparency. The original code in this case was far too big to include here, and I really didn't want to have to think up all the obfuscated names. Furthermore, it did not have the same level of functionality, so only the new version is shown (Listing 15). The code comes from a Windows GUI application that needs to process files and, as shown, report to the user if the file cannot be accessed. For localisation purposes, message strings, and windows error strings, are obtained at runtime.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    void ProcessFile(  
      HINSTANCE hinst  
    , HWND      parent  
    , LPCTSTR   fileName  
    )  
    {  
      WIN32_FIND_DATA fd;  
      HANDLE h = ::FindFirstFile(fileName, &amp;fd);  
 
      if(INVALID_HANDLE_VALUE == h)  
      {  
        DWORD err = ::GetLastError();  
        ff::windows_resource_bundle bundle(hinst);  
 
        ff::ignore_unreferenced_arguments_scope scoper;  
 
        ff::fmt(  
            ff::sinks::MessageBox(parent, &quot;Problem&quot;, MB_ICONWARNING)  
          , bundle[IDS_FMT_MISSING_FILE]   
          , filename  
          , err  
          , winstl::error_desc(err));  
      }  
      else  
      {  
        // . . . do something useful with file data  
      }  
    }  
</pre>
</td></tr><tr><td class="title">Listing 15</td></tr></table>
  </p><p> 
    Assume <tt class="code">fileName</tt> is <tt class="code">&quot;abc.def&quot;</tt>, and that no such file exists. Further assume that the module designated by <tt class="code">hinst</tt> has a string resource with the identifier <tt class="code">IDS_FMT_MISSING_FILE</tt> whose value is
  </p>
<pre class="programlisting">
      &quot;The file '{0}' could not be processed: {2}&quot;  
</pre><p> 
    In that case, a message box will be displayed, as a child of the parent window, with the type <tt class="code">MB_ICONWARNING</tt> (the yellow triangle with an exclamation mark in it),  and the message
  </p>
<pre class="programlisting">
    &quot;The file 'abc.def' could not be processed: The system cannot find the file specified&quot;  
</pre><p> 
    Obviously, there's a lot going on here: formatting, looking up resources, looking up error code strings. Let's break it down according to the separate FastFormat components at play.
  </p><p> 
    First, an instance of the <tt class="code">fastformat::windows_resource_bundle</tt> class is declared, taking <tt class="code">hinst</tt> in its constructor. This class represents a fa&ccedil;ade over the Windows Resources API functions, providing a simple mapping of id to string, throwing an exception if a given id does not represent a string resource.
  </p><p> 
    Second, the creator function  <tt class="code">fastformat::sinks::MessageBox()</tt> 
				      [<a href="#XSTLv1">XSTLv1</a>]
				 constructs an instance of the sink class <tt class="code">fastformat::sinks::MessageBox_sink</tt>, which will receive the formatted statement results and then invoke the Windows function <tt class="code">MessageBox()</tt> to display the message. In this case, the two arguments required are the filename (<tt class="code">{0}</tt>) and a temporary instance of the <tt class="code">winstl::error_desc</tt> class (<tt class="code">{2}</tt>), which is used to elicit the string form of an error code via the Windows <tt class="code">FormatMessage()</tt> function. Note that we remember the error code associated with the failure to open/stat the file before doing any error display processing, since any subsequent Windows API failure would change the thread's last error code, and lead to a potentially misleading cause being presented to the user.
  </p><p> 
    Third, you may have noticed that there are actually three format arguments: <tt class="code">filename</tt>, <tt class="code">err</tt>, and <tt class="code">winstl::error_desc(err)</tt>, but the example format string contains just two replacement parameters. By default, all format specification defect conditions result in the throwing of an exception (derived from <tt class="code">fastformat::fastformat_exception</tt>). The purpose of the scoper instance of the succinctly named <tt class="code">fastformat::ignore_unreferenced_arguments_scope</tt> class is to suppress this, and allow the string to be formatted despite the mismatch. During its lifetime it suppresses the throwing of a <tt class="code">fastformat::unreferenced_argument_exception</tt>. (We'll discuss how this works later.)
  </p><p> 
    We do this because we want to be able to use different resource strings without breaking the application. This is usually for localisation purposes, but may also be to give more information in debug builds (such as the numeric value of the error code <tt class="code">err</tt>). For example, for some locales we might want to change <tt class="code">IDS_FMT_MISSING_FILE</tt> to:
  </p>
<pre class="programlisting">
    &quot;The file '{0}' could not be processed&quot;  
</pre><p> 
    And in debug builds we might want to use the format string:
  </p>
<pre class="programlisting">
    &quot;The file '{0}' could not be processed: error code {1}: {2}&quot;  
</pre><p> 
    Note that scoper only suppresses exceptions with unreferenced arguments, however. If the format changed to 
  </p>
<pre class="programlisting">
    &quot;The file '{0}' could not be processed: please inform {3}&quot;  
</pre><p> 
    then a <tt class="code">fastformat::missing_argument_exception</tt> would be thrown, and we don't want to squash that. (If we did, we'd declare an instance of <tt class="code">fastformat::ignore_missing_arguments_scope</tt>, with the effect that <tt class="code">{3}</tt> would be replaced with the empty string.)
  </p><h3>
    Windows format strings
  </h3><p> 
    One last note on format strings on Windows. Windows message files (used via <tt class="code">FormatMessage</tt>) and MFC (used via <tt class="code">AfxFormatString*()</tt>) use a different format syntax, where the format string would instead be
  </p>
<pre class="programlisting">
      &quot;The file '%1' could not be processed: %3&quot;  
</pre><p> 
    As a convenience, the <tt class="code">windows_resource_bundle</tt> class is able to use these format strings, and performs a translation if the original contains one or more Windows replacement parameters and zero FastFormat replacement parameters. This allows an easy upgrade from MFC-based resource formatting to FastFormat, which is particularly useful if your application is localised to several locales. 
  </p><h2>
    Format specification defect handlers
  </h2><p> 
    Let's now consider the format specification defect handler mechanism. As discussed in part 1 
				      [<a href="#FF1">FF1</a>]
				, format specification defects involve both badly formed format strings, and a failure to match all replacement parameters to all given arguments. We'll consider only the mismatch case; the two aspects follow the same pattern.
  </p><p> 
    Control of mismatch behaviour involves an enumeration, a handler function prototype, a structure, and four API functions, to get+set the handler for thread+process. Thread handlers, if set, take precedence over process ones; in single-threaded builds they are the same.
  </p><p> 
    The relevant aspects of the API are shown in Listing 16. (I apologise for the long names.)
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    enum ff_replacement_code_t  
    {  
        FF_REPLACEMENTCODE_SUCCESS = 0  
      , FF_REPLACEMENTCODE_MISSING_ARGUMENT  
      , FF_REPLACEMENTCODE_UNREFERENCED_ARGUMENT  
    };   
    typedef int (*fastformat_mismatchedHandler_t)(  
      void*                 param  
    , ff_replacement_code_t code  
    , size_t                numParameters  
    , int                   parameterIndex  
    , ff_string_slice_t*    slice  
    , void*                 reserved0  
    , size_t                reserved1  
    , void*                 reserved2  
    );  
    struct ff_mismatched_handler_info_t  
    {  
      fastformat_mismatchedHandler_t handler;  
      void* param;  
    };  
    ff_mismatched_handler_info_t   
      fastformat_getThreadMismatchedHandler();  
    ff_mismatched_handler_info_t  
      fastformat_setProcessMismatchedHandler(  
        fastformat_mismatchedHandler_t handler  
      , void* param  
      );  
    . . . // same for process handlers  
</pre>
</td></tr><tr><td class="title">Listing 16</td></tr></table>
  </p><p> 
    With this, as shown in Listing 17, we're in a position to see how the <tt class="code">fastformat::ignore_unreferenced_arguments_scope</tt> class works.
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    // in namespace fastformat  
    class ignore_unreferenced_arguments_scope  
      : private mismatched_arguments_scope_base  
    {  
    public:  
      typedef ignore_unreferenced_arguments_scope  
         class_type;  
      typedef mismatched_arguments_scope_base  
         parent_class_type;  
    public:  
      ignore_unreferenced_arguments_scope()  
        : parent_class_type(class_type::handler,  
        get_this_())  
      {}  
    private:  
      void* get_this_() throw()  
      {  
        return this;  
      }  
      static int handler(  
        void*                 param  
      , ff_replacement_code_t code  
      , size_t                numParameters  
      , int                   parameterIndex  
      , ff_string_slice_t*    slice  
      , void*                 reserved0  
      , size_t                reserved1  
      , void*                 reserved2  
      )  
      {  
        class_type* pThis =  
           static_cast&lt;class_type*&gt;(param);  
        if(FF_REPLACEMENTCODE_UNREFERENCED_ARGUMENT  
           == code)  
        {  
          return +1; // Ignore unreferenced argument  
        }  
        else  
        {  
          return pThis-&gt;parent_class_type::  
             handle_default(param, code,  
             numParameters, parameterIndex, slice,  
             reserved0, reserved1, reserved2);  
          }  
      }  
 }
</pre>
</td></tr><tr><td class="title">Listing 17</td></tr></table>
  </p><p> 
    The class is derived (privately) from the class  <tt class="code">fastformat::mismatched_arguments_scope_base</tt>, which handles (de-)registration of a derived class instance and its handler method for the duration of its lifetime,  via the class <tt class="code">fastformat_setThreadMismatchedHandler()</tt>. (The use of <tt class="code">get_this_()</tt> is an old trick for avoiding compiler warnings about use of a partially constructed instance in its own member initialiser list; see 
				      [<a href="#IC++">IC++</a>]
				.)
  </p><p> 
    The meat of this component is in the derived class's <tt class="code">handler()</tt> method, which intercepts an unreferenced argument code, and instructs the FastFormat replacement engine to ignore it. All other codes are passed, via the parent class's <tt class="code">handle_default()</tt>, to the previous handler, if any, in the chain. The consequence of this is that, for the lifetime of scoper, any unreferenced arguments will not cause an <tt class="code">fastformat::unreferenced_argument_exception</tt> to be thrown. 
  </p><p> 
    You're not limited to the scoping classes provided with the distribution. FastFormat allows you to customise its behaviour in light of ill-formed format strings and/or of mismatched arguments, on a per-process and/or per-thread basis, to do whatever funky things your heart desires.
  </p><h2>
    Choosing output sinks
  </h2><p> 
    A last note on output sinks. If you're determined to squeeze out every last cycle, you might choose to use <tt class="code">stdout</tt> as your sink rather than <tt class="code">std::cout</tt>, as in:
  </p>
<pre class="programlisting">
      #include &lt;fastformat/sinks/FILE.hpp&gt;  
      //#include &lt;fastformat/sinks/ostream.hpp&gt;  
 
      FILE* stm = stdout;  
 
      // FastFormat.Format  
      ff::fmtln(  
        stm  
      , &quot;[{0}{1}]&quot;  
      , ff::to_f(12345.12345, -14, 3)  
      , ff::to_f(12345.12345, -14, 3)  
      );  
</pre><p> 
    The inconvenience with this is that you'll likely have to declare a sink variable, as shown in the example, because <tt class="code">stdout</tt> is often not an instance at all, but rather some <tt class="code">#define</tt> into part of an implementation-defined structure, such as <tt class="code">(&amp;_iob[1])</tt> for Visual C++, or <tt class="code">(&amp;_streams[1])</tt> with Borland. The same is needed for <tt class="code">stderr</tt>. 
  </p><p> 
    Note that the gains, if any, are strongly platform-dependent. On Linux it gives between 5% and 10% improvement, on Mac OS-X between 2% and 6%. On Windows, with VC++ 9 it actually slows down by a small margn. Obviously, the advice is to get it working (with <tt class="code">std::cout</tt>) and then optimise (with <tt class="code">stdout</tt>) if you really need to. That's only likely to be if you're writing to a file - using an arbitrary <tt class="code">FILE*</tt> handle rather than an arbitrary <tt class="code">fstream</tt> instance - since console/terminal output is far too much affected by other factors for such low-percentage performance improvements to be significant.
  </p><h2>
    FastFormat for logging?
  </h2><p> 
    Several people have enquired about the use of FastFormat for application logging. As we've seen in the Server Connection Log example, for some kinds of logging it's a good solution. For what I call application logging, however - the presence of statements throughout the code that allows an interested observer to follow what is happening now, and what has already happened, at a high level of granularity - the use of <tt class="code">FastFormat.Format</tt>, or any other replacement-based API 
				      [<a href="#FF1">FF1</a>]
				, is not advisable. The same goes for any library that is less than 100% type-safe. The reason is that the programmer should be able to have full confidence that an application logging statement will be processed and emit output. This is because many uses of log statements are in places in the code are impossible, or exceedingly difficult, to test, and usually these statements are the ones you most need to be able to rely on.
  </p><p> 
    I've mentioned my other, older, logging API library, Pantheios, a couple of times in this article series. I hope to write an article about that at some time in the future, and will go into more detail about the how/why/when/what of logging. For the moment, however, I'll show you a sneaky trick that allows you to use <tt class="code">FastFormat.Write</tt> (or <tt class="code">FastFormat.Format</tt>, if you must) with Pantheios.
  </p><p> 
    The Pantheios application layer contains severity level pseudo-constant symbols that are actually stateless global instances of specialisations of a severity level class template:
  </p>
<pre class="programlisting">
      namespace Pantheios  
      {  
        namespace  
        {  
          static level&lt;PANTHEIOS_SEV_DEBUG&gt; debug;  
          . . . // and so on  
          static level&lt;SEV_ALERT&gt; alert;  
          static level&lt;SEV_EMERGENCY&gt; emergency;  
        }  
      }  
</pre><p> 
    These are not declared <tt class="code">const</tt>, even though no-one should be attempting any mutations of them, precisely so they can be used as 'sinks' to FastFormat, by defining the following overload of <tt class="code">fastformat::sinks::fmt_slices</tt>
				      [<a href="#FF2">FF2</a>]
				:
  </p>
<p> 
<table class="sidebartable"><tr><td>
<pre class="programlisting">
    // in namespace fastformat::sinks  
    template &lt;int L&gt;  
    pantheios::level&lt;L&gt;&amp; fmt_slices(  
      pantheios::level&lt;L&gt;&amp;     sink  
    , int                      /* flags */  
    , size_t                   /* cchTotal */  
    , size_t                   numResults  
    , ff_string_slice_t const* results)  
    {  
STLSOFT_STATIC_ASSERT(sizeof(
  pantheios::pan_slice_t) == 
  sizeof(fastformat::ff_string_slice_t));  
STLSOFT_STATIC_ASSERT(offsetof(
  pantheios::pan_slice_t, len) == 
  offsetof(fastformat::ff_string_slice_t, 
  len));  
 
      pantheios::pantheios_log_n(  
        sink  
      , numResults  
      , stlsoft::sap_cast&lt;pantheios::pan_slice_t const*&gt;(results)  
      );  
      return sink;  
    }  
</pre>
</td></tr><tr><td class="title">Listing 18</td></tr></table>
  </p><p> 
    This 'works' because the definitions of <tt class="code">ff_string_slice_t</tt> and <tt class="code">pan_slice_t</tt> - the thing <tt class="code">ff_string_slice_t</tt> was copied from in the first place - are identical, and therefore binary compatible. The two static asserts 
				      [<a href="#IC++">IC++</a>]
				 are there to ensure that any changes that invalidate that assumption are not missed. Then it's as simple as casting from one array of string alices to the other, and passing to the core Pantheios logging function.
  </p><p> 
    This allows code such as the following:
  </p>
<pre class="programlisting">
      catch(std::exception&amp; x)  
      {  
        ff::write(pan::warning,  
           &quot;Something bad has happened: &quot;, x);  
      }  
</pre><p> 
    and
  </p>
<pre class="programlisting">
      HRESULT GetFilter(dimension_t dimension,  
         short index, BSTR* filter)  
      {  
        // NOTE: can pass 'dimension' variable   
        // directly if string access shims are  
        // defined for the dimension_t enum  
        ff::write(pan::debug, &quot;GetFilter(dimension=&quot;,  
           dimension, &quot;; index=&quot;, index, &quot;, ...)&quot;);  
</pre><p> 
    As I said at the start of this section, there are several reasons to prefer using a proper logging solution, such as Pantheios, but this technique will get you a fair way along to a good solution.
  </p><h2>
    Summary
  </h2><p> 
    This article completes the introduction to FastFormat, a C++ library that applies advanced generic conversion techniques to provide robust, flexible and efficient formatting, providing answers to the deficiencies of the current standard and widely used third-party libraries. It is in ongoing development, and readers are invited to use, criticise and contribute, as they see fit.</p><h2>
    References
  </h2><p class="bibliomixed"><a name="FF1"></a> 
    [FF1] 'An Introduction to FastFormat, part 1: The State of the Art', Matthew Wilson, Overload #89, February 2009; <a href="http://accu.org/index.php/journals/c249/">http://accu.org/index.php/journals/c249/</a>
  </p><p class="bibliomixed"><a name="FF2"></a> 
    [FF2] 'An Introduction to FastFormat, part 2: Custom Argument and Sink Types', Matthew Wilson, Overload #90, April 2009; <a href="http://accu.org/index.php/journals/c251/">http://accu.org/index.php/journals/c251/</a>
  </p><p class="bibliomixed"><a name="IC++"></a> 
    [IC++] Imperfect C++, Matthew Wilson, Addison-Wesley 2004; <a href="http://www.imperfectcplusplus.com/">http://www.imperfectcplusplus.com/</a>
  </p><p class="bibliomixed"><a name="PAN"></a> 
    [PAN] The Pantheios Logging API Library, <a href="http://www.pantheios.org/">http://www.pantheios.org/</a>; to see why it's the best choice in C++ logging APIs, check out <a href="http://www.pantheios.org/performance.html">http://www.pantheios.org/performance.html#sweet-spot</a>, which shows graphically how Pantheios can be up to two-orders of magnitude faster than the rest.
  </p><p class="bibliomixed"><a name="PragProg"></a> 
    [PragProg] The Pragmatic Programmer, Dave Thomas and Andy Hunt, Addison-Wesley, 2000; <a href="http://www.pragmaticbookshelf.com/">http://www.pragmaticbookshelf.com/</a>
  </p><p class="bibliomixed"><a name="SO"></a> 
    [SO] <a href="http://www.stackoverflow.com/questions/586410/">http://www.stackoverflow.com/questions/586410/ </a>
  </p><p class="bibliomixed"><a name="XSTLv1"></a> 
    [XSTLv1] Extended STL, volume 1, Matthew Wilson, Addison-Wesley 2007; <a href="http://www.extendedstl.com/">http://www.extendedstl.com/</a>
  </p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
