    <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  :: Letters to the Editor</title>
        <link>https://members.accu.org/index.php/articles/237</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 + Letters to the Editor + Overload Journal #62 - Aug 2004</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/c184/">Journal Columns</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c186/">LettersEditor</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/c150/">62</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+186+150/">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;Letters to the Editor</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 August 2004 22:52:11 +01:00 or Sun, 01 August 2004 22:52:11 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e16" id="d0e16"></a></h2>
</div>
<p>Dear Editor</p>
<p>I was reading Stefan Heinzmann's paper &quot;The Tale of a Struggling
Template Programmer&quot; in June 2004 Overload, and I could not help
thinking that a 2 page long code listing cannot possibly be a
proper solution to such a simple problem!</p>
<p>To make the following discussion clearer, this is Stefan's
declaration of the <tt class="function">lookup</tt> function:</p>
<pre class="programlisting">
template&lt;class EKey, class EVal, unsigned n,
         class Key, class Val&gt;
EVal lookup(const Pair&lt;EKey, EVal&gt;(&amp;tbl)[n],
            const Key &amp; key, const Val &amp; def)
</pre>
<p>As it is clearly stated by Phil Bass in his solution, the real
problem in this declaration is the fact that we do not really want
the types of the <i class="parameter"><tt>key</tt></i> and
<tt class="function">def</tt> function arguments to be
automatically deduced by compiler. What instead we want is to force
the compiler to deduce the types of the <tt class="type">EKey</tt>
and <tt class="type">EVal</tt> template arguments by looking at the
type of the tbl's <tt class="classname">Pair</tt> elements, and
then use these deduced types as the types of the <i class=
"parameter"><tt>key</tt></i> and <tt class="function">def</tt>
function arguments.</p>
<p>Using pseudo code this is how it would look:</p>
<pre class="programlisting">
template&lt;class K, class V, int N&gt;
V lookup(const Pair&lt;K, V&gt;(&amp;tbl)[N],
         typeof(K) key,
         typeof(V) const &amp; def)
</pre>
<p>Now in order to translate this pseudo code into real code the
only thing we need is a way to name the types of the <tt class=
"classname">Pair</tt>'s <i class="parameter"><tt>K</tt></i> and
<i class="parameter"><tt>V</tt></i> template arguments. And by far
the simplest way to create a name for the type of a template
argument is by creating a <tt class="literal">typedef</tt> within
the definition of the template itself:</p>
<pre class="programlisting">
template&lt;class K, class V&gt;
struct Pair {
  typedef K key_type;
  typedef V mapped_type;
  key_type key;
  mapped_type value;
};
</pre>
<p>Once this is done we can rewrite the signature of the <tt class=
"function">lookup</tt> function this way:</p>
<pre class="programlisting">
template&lt;class K, class V, int N&gt;
typename Pair&lt;K, V&gt;::mapped_type
    const &amp; lookup(const Pair&lt;K, V&gt;(&amp;tbl)[N],
           typename Pair&lt;K, V&gt;::key_type key,
           typename Pair&lt;K, V&gt;::mapped_type
                       const &amp; default_value);
</pre>
<p>Which solves pretty much all of Stefan's problems related to the
<tt class="function">lookup</tt> function (no more ugly casts,
function can return the result by reference).</p>
<p>I am attaching the code for the complete solution at the bottom
of this mail.</p>
<p>In order to keep the code as simple and as clean as possible, I
have decided to provide global definitions of the &lt; and ==
operators for the Pair type instead of resorting to a custom
function object. Given that the Pair type is a very simple type
whose usage is entirely under our control I feel this is not at all
inappropriate.</p>
<p>Kind Regards</p>
<p><span class="emphasis"><em>Renato Mancuso</em></span></p>
<pre class="programlisting">
#include &lt;iostream&gt;
      // for std::cout, std::cerr, std::endl
#include &lt;algorithm&gt; // for std::lower_bound
#include &lt;cassert&gt;   // for the assert macro

// This is the definition of the Pair
// template class.
// We do not declare a constructor since
// we want this struct to be a POD type.
template&lt;class K, class V&gt;
struct Pair {
  typedef K key_type;
  typedef V mapped_type;
  key_type key;
  mapped_type value;
};

// These are the global operator &lt; and == for
// the Pair template class. They define a weak
// ordering relationship based on the value of
// the Pair's key data member. NOTE: Comeau
// 4.3.3 STL requires the declaration of the
// complete set of relational operators. This
// is not correct according to the Standard.
template&lt;class K, class V&gt;
inline bool operator&lt;(const Pair&lt;K, V&gt; &amp; lhs,
                    const Pair&lt;K, V&gt; &amp; rhs) {
  return lhs.key &lt; rhs.key;
}
template&lt;class K, class V&gt;
inline bool operator==(const Pair&lt;K, V&gt; &amp; lhs,
                    const Pair&lt;K, V&gt; &amp; rhs) {
  return lhs.key == rhs.key;
}

// This is the lookup function. It assumes
// that tbl's elements are sorted according
// to the // global &lt; and == operators.
template&lt;class K, class V, int N&gt;
typename Pair&lt;K, V&gt;::mapped_type const &amp;
      lookup(const Pair&lt; K, V &gt;( &amp;tbl )[ N ],
          typename Pair&lt;K, V&gt;::key_type key,
          typename Pair&lt;K, V&gt;::mapped_type
                     const &amp; default_value) {
  typedef Pair&lt;K, V&gt; pair_type;
  typedef const pair_type * iterator_type;
  const pair_type target = { key };
  iterator_type first = tbl;
  iterator_type last  = tbl + N;
  iterator_type found =
        std::lower_bound(first, last, target);
  if((found != last) &amp;&amp; (*found == target)) {
    return found-&gt;value;
  }
  return default_value;
}
// This template function checks that the
// table is sorted and that the key values
// are unique.
// Since this is a template function, it is
// only instantiated if it is called.
template&lt;class T, int N&gt;
bool is_sorted(T(&amp;tbl)[N]) {
  for(int i = 0; i &lt; N - 1; ++i) {
    if((tbl[i+1] &lt; tbl[i])
        || (tbl[i+1] == tbl[i])) {
      std::cerr &lt;&lt; &quot;Element at index &quot; &lt;&lt; i+1
                &lt;&lt; &quot; is not greater than its &quot; 
                &lt;&lt; &quot;predecessor.\n&quot;;
      return false;
    }
  }
  return true;
}

// This is our test array mapping error codes
// to error messages.
const Pair&lt;int, char const *&gt; table[] = {
  { 0, &quot;OK&quot; },
  { 6, &quot;minor glitch in self-destruction module&quot; },
  { 13, &quot;Error logging printer out of paper&quot; },
  { 101, &quot;Emergency cooling system inoperable&quot; },
  { 2349, &quot;Dangerous substance released&quot; },
  { 32767, &quot;Game over, you lost&quot; }
};

// This is how we check that the array is
// sorted. It is done only in DEBUG builds.
#if !defined(NDEBUG)
namespace {
  struct check_sorted {
    check_sorted() { assert(is_sorted(table)); }
  };
  check_sorted checker;
}
#endif /* !defined(NDEBUG) */

int main() {
  // no need to cast the third argument to a
  // (char const*) since now the type of the
  // default_value argument is deduced from
  // the type of the elements of table[]...
  const char* result = lookup( table, 6, 0 );

  std::cout &lt;&lt; (result ? result : &quot;not found&quot;)
            &lt;&lt; std::endl;
  std::cout &lt;&lt; lookup(table, 5, &quot;unknown error&quot;)
            &lt;&lt; std::endl;
  return 0;
}
</pre></p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
