    <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  :: A Template Programmer&#8217;s Struggles Resolved</title>
        <link>https://members.accu.org/index.php/articles/215</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 + Overload Journal #61 - Jun 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/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/c151/">61</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+151/">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;A Template Programmer&#8217;s Struggles Resolved</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 June 2004 14:26:10 +01:00 or Tue, 01 June 2004 14:26:10 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;      <p>This article is the result of the conversations between
      the two authors (Phil Bass and Stefan Heinzmann) that were
      triggered by the latter's article in this very issue of
      Overload [<a href="#Heinzmann">Heinzmann</a>]. Stefan
      originally wanted to have the resolution of the problems
      outlined in his article published in the next issue in order
      to keep you in creative suspension for a while, but the
      Editor found that to be too cruel, so we tried to finish this
      article in record time.</p>

      <p>Article [<a href="#Heinzmann">Heinzmann</a>] ended with 4
      unsolved problems which are repeated here:</p>

      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>It requires the ugly cast for passing the null
            pointer as the third argument to <tt class=
            "methodname">lookup</tt></p>
          </li>

          <li>
            <p><tt class="methodname">lookup</tt> returns the
            result by value, which can be inefficient</p>
          </li>

          <li>
            <p>It is still unclear why I couldn't use the
            <tt class="literal">typedef</tt>s from <tt class=
            "classname">std::binary_function</tt> in the <tt class=
            "function">LessKey</tt> predicate (only with GCC)</p>
          </li>

          <li>
            <p>Neither do I know why the compiler wanted to convert
            the wrong way between <i class=
            "parameter"><tt>Val</tt></i> and <i class=
            "parameter"><tt>EVal</tt></i></p>
          </li>
        </ul>
      </div>

      <p>The first two problems relate to the <tt class=
      "methodname">lookup</tt> function template, while the last
      two problems relate to the <tt class="function">LessKey</tt>
      predicate. In addition, the text itself lists as a fifth
      problem: How to ensure at compile time that the lookup table
      is sorted. Just for a change, let's tackle those
      problems in reverse order.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e76" id=
        "d0e76"></a>Ensuring the Lookup Table is Sorted</h2>
      </div>

      <p>Thaddaeus Frogley suggested that rather than sorting the
      table at compile time, which may be impossible, the debug
      build could check the sorting when the program starts up. You
      would need to write a function that checks the table sorting
      and call it in an assert macro that is run at program
      startup. As an additional service, the checking code could
      generate a sorted version of the table in a format that can
      be cut and pasted into the source code, so that the burden of
      keeping the table sorted is not on the struggling programmer.
      We'll not actually show any code for this here, as we
      believe that it is fairly straightforward. Furthermore, this
      issue was not the main point in [<a href=
      "#Heinzmann">Heinzmann</a>] anyway.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2>The
        <tt class="function">LessKey</tt> Predicate</h2>
      </div>

      <p>Here, we owe you an explanation why the <tt class=
      "literal">typedef</tt>s in the <tt class=
      "classname">binary_function</tt> base class could not be used
      in the definition of <tt class=
      "methodname">LessKey::operator()</tt>. It turns out that this
      is because of the name lookup rules, namely two-phase lookup.
      If you want to know the full story you need to turn to The
      Book [<a href="#Vandevoorde-">Vandevoorde-</a>] chapter
      9.4.2, but here's the bottom line:</p>

      <p>As <tt class="classname">std::binary_function</tt> is a
      base class for <tt class="classname">LessKey</tt> that
      depends on <tt class="classname">LessKey</tt>'s
      template parameters, it is called a dependent base class. The
      C++ standard says that nondependent names are not looked up
      in dependent base classes. Hence a standard conforming
      compiler will not find <span class="type">result_type</span>
      and its siblings and emit an error message. The error
      messages that were actually emitted by GCC weren't
      particularly helpful, in particular the mentioning of
      typename was misleading, but the code was definitely wrong.
      So what can we do about it? There are a number of
      possibilities here, though none are particularly
      appealing:</p>

      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>Dodge the issue in the way Stefan did it, i.e. by
            not using <span class="type">result_type</span> etc.
            inside <tt class="classname">LessKey</tt>. The downside
            of this is that the fairly complicated element type
            must be written out several times.</p>
          </li>

          <li>
            <p>Explicitly qualify the <tt class=
            "literal">typedef</tt> names with the name of the base
            class. This makes the names dependent, therefore they
            are looked up and found in the base class. However that
            removes the whole point of using the <tt class=
            "literal">typedef</tt>s, because the base class name is
            a complicated template.</p>
          </li>

          <li>
            <p>Bring the <tt class="literal">typedef</tt> names
            into the scope of the derived class with a using
            declaration. That doesn't save any typing either,
            because the base class name needs to be spelled out,
            too.</p>
          </li>

          <li>
            <p>Add another <tt class="literal">typedef</tt> to the
            derived class. That is also fairly verbose, so it may
            not be an improvement over the first solution.</p>
          </li>
        </ul>
      </div>

      <p>That's disappointing, isn't it? It means that
      deriving from <tt class="classname">std::binary_function</tt>
      in order to make the predicate adaptable according to the
      rules of the STL is only half as useful as you'd wish
      it to be. It makes you wonder whether you want to derive from
      <tt class="classname">std::binary_function</tt> at all. After
      all, you can make your predicate adaptable by providing the
      required typedefs yourself, like this:</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
struct LessKey {
  typedef bool result_type;
  typedef const Pair&lt;Key,Val&gt; &amp;first_argument_type;
  typedef first_argument_type second_argument_type;
  result_type operator()(first_argument_type a,
                         second_argument_type b) const
  { return a.key &lt; b.key; }
};
</pre>

      <p>If you don't want the predicate to be adaptable, you
      can apply a clever trick that appeared in [<a href=
      "#Sposato">Sposato</a>]: You make the predicate work on the
      key type directly. This removes the need to construct an
      element with all its associated problems mentioned in
      [<a href="#Heinzmann">Heinzmann</a>]. If we needn't
      construct an element, we need no default constructor for the
      <i class="parameter"><tt>Val</tt></i> type either, which is
      an additional advantage. Here's the code:</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
struct CleverLessKey {
  typedef const Pair&lt;Key,Val&gt; Elem;
  bool operator()(Elem &amp;elem, const Key &amp;key) const
  { return elem.key &lt; key; }
  bool operator()(const Key &amp;key, Elem &amp;elem) const
  { return key &lt; elem.key; }
};
</pre>

      <p>Note the overloading of <tt class=
      "methodname">operator()</tt> to allow passing the arguments
      in any order. Inside the lookup function template the key can
      now be passed directly to <tt class=
      "function">equal_range</tt>:</p>
      <pre class="programlisting">
template&lt;typename EKey, typename EVal,
         unsigned n, typename Key, typename Val&gt;
         EVal lookup(const Pair&lt;EKey,EVal&gt;(&amp;tbl)[n],
         const Key &amp;key, const Val &amp;def) {
  typedef CleverLessKey&lt;EKey,EVal&gt; Pred;
  typedef const Pair&lt;EKey,EVal&gt; Elem;
  std::pair&lt;Elem*,Elem*&gt; range
        = std::equal_range(tbl, tbl+n, key, Pred());
  if(range.first != range.second)
    return range.first-&gt;val;
  return def;
}
</pre>

      <p>This bends the intuitive rule of what a good predicate is;
      ordinarily you would think both argument types had to be the
      same, but as far as we know there's nothing in the C++
      standard that would make this illegal. It certainly works
      with VC++ 7.1 and GCC 3.3.</p>

      <p>The Comeau compiler [<a href="#comeau">comeau</a>]
      disagrees, however. Apparently, the library implementation
      used by Comeau contains compile-time concept checks that
      verify whether the two argument types of the predicate are
      the same. As ours are not, those checks fail and the compiler
      rejects the code. We feel that this is overly
      restrictive.</p>

      <p>That leads us to the weird error mentioned in [<a href=
      "#Heinzmann">Heinzmann</a>] where the compiler apparently
      wanted to convert an <span class="type">int</span> to a
      <span class="type">const char [4]</span>. We owe you an
      explanation here, too. Let us repeat the relevant code where
      the error occurs:</p>
      <pre class="programlisting">
template&lt;typename EKey, typename EVal,
         unsigned n, typename Key, typename Val&gt;
         EVal lookup(const Pair&lt;EKey,EVal&gt;(&amp;tbl)[n],
         const Key &amp;key, const Val &amp;def) {
  typedef LessKey&lt;EKey,EVal&gt; Pred;
  typedef const Pair&lt;EKey,EVal&gt; Elem;
  Elem entry = { key, Val() }; // error here
  std::pair&lt;Elem*,Elem*&gt; range
        = std::equal_range(tbl, tbl+n, entry, Pred());
  if(range.first != range.second)
    return range.first-&gt;val;
  return def;
}
</pre>

      <p>The error message was strange, but there's indeed an
      error. The compiler correctly deduces the following type for
      <i class="parameter"><tt>Val</tt></i>, namely <span class=
      "type">const char [4]</span>. That means that <tt class=
      "function">Val()</tt> tries to default construct a temporary
      of type <span class="type">const char [4]</span>, which is
      impossible. No conversion from <span class="type">int</span>
      to <span class="type">const char [4]</span> is involved, the
      error displayed by the compiler is again rather misleading
      here.</p>

      <p>The fix employed in [<a href="#Heinzmann">Heinzmann</a>]
      was correct, but there is another, more elegant
      possibility:</p>
      <pre class="programlisting">
template&lt;typename EKey, typename EVal,
         unsigned n, typename Key, typename Val&gt;
EVal lookup(const Pair&lt;EKey,EVal&gt;(&amp;tbl)[n],
         const Key &amp;key, const Val &amp;def) {
  typedef LessKey&lt;EKey,EVal&gt; Pred;
  typedef const Pair&lt;EKey,EVal&gt; Elem;
  Elem entry = { key }; // second part of Pair
                        // omitted
  std::pair&lt;Elem*,Elem*&gt; range
        = std::equal_range(tbl, tbl+n, entry, Pred());
  if(range.first != range.second)
    return range.first-&gt;val;
  return def;
}
</pre>

      <p>As you may have noted, it is not actually necessary to
      explicitly initialize the <tt class="varname">val</tt> member
      of the variable <tt class="varname">entry</tt>, as we
      don't use it anyway. Omitting the initializer for
      <tt class="varname">val</tt> causes it to be
      value-initialized, which in practice does the same as calling
      <tt class="function">EVal()</tt> explicitly.</p>

      <p>Anyway, we will use our clever predicate henceforth,
      despite the problems with the Comeau compiler.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2>The
        <tt class="function">lookup</tt> Function Template</h2>
      </div>

      <p>Now that we've got those niggles out of the way, we
      can turn to the remaining problems. Remember what the
      question was: Given the following program fragment, how can
      we implement the <tt class="function">lookup()</tt> function
      as a function template that works for arbitrary
      instantiations of <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt>?</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
struct Pair {
  Key key;
  Val val;
};

const Pair&lt;int, const char*&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 substances released&quot; },
  { 32767, &quot;Game over, you lost&quot; }
};

int main() {
  const char *result = lookup(table,6,(char*)0);
  std::cout &lt;&lt; (result ? result : &quot;not found&quot;)
            &lt;&lt; std::endl;
}
</pre>

      <p>The implementation we arrived at in the last chapter still
      has those two problems:</p>

      <div class="itemizedlist">
        <ul type="disc">
          <li>
            <p>It requires an ugly cast for passing the null
            pointer as the third argument to lookup.</p>
          </li>

          <li>
            <p><tt class="function">lookup</tt> returns the result
            by value, which can be inefficient.</p>
          </li>
        </ul>
      </div>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e272" id=
        "d0e272"></a>Replacing <tt class=
        "function">equal_range</tt> by <tt class=
        "function">lower_bound</tt></h2>
      </div>

      <p>First, note that the <tt class="function">lookup()</tt>
      function given above is based on <tt class=
      "function">std::equal_range()</tt>, but actually behaves more
      like <tt class="function">std::lower_bound()</tt>. It returns
      the mapped value of the first element matching the key, if
      any. Since <tt class="function">lower_bound()</tt> is a
      simpler and slightly more efficient algorithm we will use it
      in the subsequent code samples. However, it is a bit trickier
      to use, as you'll see shortly.</p>

      <p>While <tt class="function">equal_range</tt> returns a pair
      of iterators, <tt class="function">lower_bound</tt> returns
      just one. If there are suitable elements (according to the
      predicate) in the collection, the returned iterator points to
      the first one found. Otherwise it points to the place where
      such an element could be inserted without breaking the
      sorting order. This makes it more complicated to test for
      success. Here's what <tt class="function">lookup</tt>
      would look like using <tt class="function">lower_bound</tt>
      instead of <tt class="function">equal_range</tt>:</p>
      <pre class="programlisting">
template&lt;typename EKey, typename EVal,
         unsigned n, typename Key, typename Val&gt;
EVal lookup(const Pair&lt;EKey,EVal&gt;(&amp;tbl)[n],
         const Key &amp;key, const Val &amp;def) {
  CleverLessKey&lt;EKey,EVal&gt; pred;
  const Pair&lt;EKey,EVal&gt; *pos
        = std::lower_bound(tbl, tbl+n, key, pred);
  if(pos == tbl+n || pred(key,*pos))
    return def;
  return pos-&gt;val;
}
</pre>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e313" id=
        "d0e313"></a>Generalization for Arbitrary Maps</h2>
      </div>

      <p>Lets take a step back and look at the problem from a
      generic angle: Why restrict ourselves to arrays? Surely, it
      should be possible to write <tt class=
      "function">lookup()</tt> so that it works with any map-like
      container. In particular, we would expect to be able to
      write:</p>
      <pre class="programlisting">
// ... table definition, etc. as before ...
using namespace std;
int main() {
  map&lt;int, const char*&gt; message_map;
  message_map[6]
        = &quot;Minor glitch in self-destruction module&quot;;
  cout &lt;&lt; lookup(message_map, 6, &quot;not found&#8221;)
       &lt;&lt; endl;
  cout &lt;&lt; lookup(message_map, 6, 0) &lt;&lt; endl;
  cout &lt;&lt; lookup(table, 6, &quot;not found&quot;) &lt;&lt; endl;
  cout &lt;&lt; lookup(table, 6, 0) &lt;&lt; endl;
}
</pre>

      <p>Although this is a slightly different problem, it points
      the way towards a solution to the original problem that
      removes the remaining blemishes in Stefan's code.</p>

      <p>The lookup function needs to be implemented in quite
      different ways for maps and arrays. For a map, lookup should
      call <tt class="methodname">std::map&lt;&gt;::find()</tt>;
      for an array, it should call <tt class=
      "function">std::lower_bound()</tt>. These two functions have
      different interfaces. The former is a member function taking
      a single parameter; the latter is a non-member function
      taking four parameters (for the overload we need). Somehow,
      the lookup function template must deduce these differences
      from the type of the container passed to it.</p>

      <p>In principle, we could just provide separate overloads for
      maps and arrays:</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
const Val&amp; lookup(const std::map&lt;Key,Val&gt;&amp;,
                  const Key&amp;, const Val&amp;);

template&lt;typename Key, typename Val, unsigned n&gt;
const Val&amp; lookup(const Pair&lt;Key,Val&gt;(&amp;)[n],
                  const Key&amp;, const Val&amp;);
</pre>

      <p>But that gets us back to where we came in. Stefan's
      article was all about the difficulties of implementing the
      second of those <tt class="function">lookup()</tt> function
      overloads.</p>

      <p>An alternative approach treats lookup as an algorithm that
      can be applied to any map-like container. There is a single
      <tt class="function">lookup()</tt> function, but there can be
      several types of &#8220;map&#8221;. Or, more precisely, we
      define a generic Map concept, write the <tt class=
      "function">lookup()</tt> function template in terms of the
      Map interface and provide as many implementations of the Map
      concept as we need (including <tt class=
      "classname">std::map&lt;&gt;</tt>s and arrays of <tt class=
      "classname">Pair&lt;&gt;</tt>s).</p>
      <pre class="programlisting">
// pseudo-code
template&lt;typename Map&gt;
const MapVal&amp; lookup(const Map&amp;, const MapKey&amp;,
                     const MapVal&amp;);
</pre>

      <p>Here, we have used <i class=
      "parameter"><tt>MapKey</tt></i> and <i class=
      "parameter"><tt>MapVal</tt></i> to stand for the Map's
      key and mapped value types. In real C++ code these types
      would be deduced from the Map type. In the case of <tt class=
      "classname">std::map&lt;&gt;</tt> the <i class=
      "parameter"><tt>MapKey</tt></i> and <i class=
      "parameter"><tt>MapVal</tt></i> types are immediately
      available: <i class="parameter"><tt>MapKey</tt></i> is
      <tt class="classname">std::map&lt;&gt;::key_type</tt> and
      <i class="parameter"><tt>MapVal</tt></i> is <tt class=
      "classname">std::map&lt;&gt;::mapped_type</tt>. In the case
      of arrays things are less straightforward. Arrays are not
      classes, so we can't add nested <tt class=
      "literal">typedef</tt>s. Instead we can use the <i class=
      "firstterm">traits class technique</i>.</p>
      <pre class="programlisting">
template&lt;typename Map&gt;
const typename map_traits&lt;Map&gt;::mapped_type&amp;
lookup(const Map&amp; map,
       const typename map_traits&lt;Map&gt;::key_type&amp;
                   target_key,
       const typename map_traits&lt;Map&gt;::mapped_type&amp;
                   default_value);
</pre>

      <p>Now we can put information about the differences between
      maps and arrays in the traits class and use that information
      in our implementation of <tt class=
      "function">lookup()</tt>.</p>

      <p>Note that now there's only one template parameter
      for the compiler to deduce: The type of the map itself. Only
      the first argument to the <tt class="function">lookup</tt>
      function participates in this deduction, as the types of the
      other arguments are dependent on the result of this
      deduction. This greatly reduces the chance for deduction
      problems such as ambiguities.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e405" id=
        "d0e405"></a>Implementation of <tt class=
        "function">lookup()</tt> Traits</h2>
      </div>

      <p>As noted above, <tt class="function">lookup()</tt> will
      need to call either <tt class=
      "methodname">std::map&lt;&gt;::find()</tt> or <tt class=
      "function">std::lower_bound()</tt>. A <tt class=
      "methodname">map_traits&lt;&gt;::find()</tt> function is
      introduced to hide this from the <tt class=
      "function">lookup()</tt> function itself. Then <tt class=
      "function">lookup()</tt> needs to check whether the key was
      found and return either the default value or the value part
      of the element matching the key. Here, we use a <tt class=
      "methodname">map_traits&lt;&gt;::end()</tt> function to get
      the appropriate past-the-end iterator for the &#8216;key
      found' test. Retrieving the mapped value via an
      iterator depends on the element type (not the map type), so
      an element traits template with a <tt class=
      "methodname">mapped_value()</tt> member is used for that.</p>

      <p>The traits functions represent operations that might be
      useful in other contexts. In those cases writing</p>
      <pre class="programlisting">
map_element_traits&lt;Map&gt;::mapped_value(element)
</pre>

      <p>for example, is both tedious and verbose. So, we provide
      nonmember wrapper functions to simplify the code in these
      situations and take advantage of them in the <tt class=
      "function">lookup()</tt> function itself.</p>
      <pre class="programlisting">
// The mapped_value() convenience function
template&lt;typename Elem&gt;
inline
const typename map_element_traits&lt;Elem&gt;::mapped_type&amp;
mapped_value(const Elem&amp; element) {
  return map_element_traits&lt;Elem&gt;::mapped_value(element);
}

// The find() convenience function
template&lt;typename Map&gt;
inline
typename map_traits&lt;Map&gt;::const_iterator
find(const Map&amp; map,
     const typename map_traits&lt;Map&gt;::key_type&amp; key) {
  return map_traits&lt;Map&gt;::find(map, key);
}

// The lookup() function
template&lt;typename Map&gt;
const typename map_traits&lt;Map&gt;::mapped_type&amp;
lookup(const Map&amp; map,
       const typename map_traits&lt;Map&gt;::key_type&amp; target_key,
       const typename map_traits&lt;Map&gt;::mapped_type&amp; default_value) {
  typename map_traits&lt;Map&gt;::const_iterator i
        = find(map, target_key);
  return (i == end(map))
        ? default_value : mapped_value(*i);
}
</pre>

      <p>The traits templates are declared (but not defined) and
      then specializations are defined for each of the map-like
      containers we wish to support. This prevents the
      instantiation of the traits templates with unexpected
      template arguments (e.g. via template argument deduction),
      which should help to minimize the number of incomprehensible
      error messages if the programmer makes a mistake.</p>
      <pre class="programlisting">
template&lt;typename Elem&gt; struct map_element_traits;
template&lt;typename Map&gt; struct map_traits;
</pre>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e452" id=
        "d0e452"></a>Traits for <tt class=
        "classname">std::map&lt;&gt;</tt></h2>
      </div>

      <p>The traits templates for <tt class=
      "classname">std::map&lt;&gt;</tt> are straightforward. A
      partial specialisation of the map element traits template is
      provided for any <tt class=
      "classname">std::pair&lt;&gt;</tt>.</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
struct map_element_traits&lt; std::pair&lt;Key,Val&gt; &gt; {
  typedef std::pair&lt;Key,Val&gt; value_type;
  typedef typename value_type:: first_type key_type;
  typedef typename value_type::second_type mapped_type;

  static const key_type&amp; key(
        const value_type&amp; element) {
    return element.first;
  }

  static const mapped_type&amp; mapped_value(
        const value_type&amp; element) {
    return element.second;
  }
};
</pre>

      <p>Similarly, a partial specialization of the map traits
      template is provided for any <tt class=
      "classname">std::map&lt;&gt;</tt>.</p>
      <pre class="programlisting">
template&lt;typename Key, typename T, typename Cmp,
         typename A&gt;
struct map_traits&lt; std::map&lt;Key,T,Cmp,A&gt; &gt; {
  typedef std::map&lt;Key,T,Cmp,A&gt; map_type;
  typedef typename map_type::key_type key_type;
  typedef typename map_type::mapped_type mapped_type;
  typedef typename map_type::value_type value_type;
  typedef typename map_type::const_iterator const_iterator;

  static const_iterator begin(const map_type&amp; map)
  { return map.begin(); }

  static const_iterator end(const map_type&amp; map)
  { return map.end(); }

  static const_iterator find(const map_type&amp; map,
                             const key_type&amp; key)
  { return map.find(key); }
};
</pre>

      <p>These traits classes adapt <tt class=
      "classname">std::map</tt> for use with our <tt class=
      "function">lookup()</tt> function.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e482" id=
        "d0e482"></a>Traits for Arrays of Key,Value Pairs</h2>
      </div>

      <p>The traits for arrays of <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt> are similar to those for
      <tt class="classname">std::map&lt;&gt;</tt>. There is a
      partial specialisation of <tt class=
      "classname">map_element_traits&lt;&gt;</tt> for <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt>.</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val&gt;
struct map_element_traits&lt; Pair&lt;Key,Val&gt; &gt; {
  typedef Pair&lt;Key,Val&gt; value_type;
  typedef Key key_type;
  typedef Val mapped_type;

  static const key_type&amp; key(
        const value_type&amp; element)
  { return element.key; }

  static const mapped_type&amp; mapped_value(
        const value_type&amp; element)
  { return element.val; }
};
</pre>

      <p>And there is a partial specialisation of <tt class=
      "classname">map_traits&lt;&gt;</tt> for arrays of <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt>.</p>
      <pre class="programlisting">
template&lt;typename Key, typename Val, unsigned n&gt;
struct map_traits&lt; Pair&lt;Key,Val&gt;[n] &gt; {
  typedef Key key_type;
  typedef Val mapped_type;
  typedef Pair&lt;Key,Val&gt; value_type;
  typedef const value_type* const_iterator;

  static const_iterator begin(
        const value_type (&amp;map)[n])
  { return &amp;map[0]; }

  static const_iterator end(
        const value_type (&amp;map)[n])
  { return &amp;map[n]; }

  static const_iterator find(
        const value_type (&amp;map)[n],
        const key_type&amp; target_key) {
    const_iterator i = std::lower_bound(begin(map),
          end(map), target_key,
          key_value_compare&lt;value_type&gt;());
    return (i == end(map) || key(*i) != target_key)
          ? end(map) : i;
  }
};
</pre>

      <p>The <tt class="function">find()</tt> function uses
      <tt class="function">lower_bound()</tt> passing a key
      comparison predicate with two asymmetric function call
      operators. The predicate class is generated from the
      following template:</p>
      <pre class="programlisting">
template&lt;typename Elem&gt;
struct key_value_compare {
  typedef typename
    map_element_traits&lt;Elem&gt;::key_type key_type;
  typedef typename
    map_element_traits&lt;Elem&gt;::value_type value_type;

  bool operator()(const value_type&amp; x,
                  const value_type&amp; y) const {
    return map_element_traits&lt;Elem&gt;::key(x) &lt;
           map_element_traits&lt;Elem&gt;::key(y);
  }

  bool operator()(const value_type&amp; elem,
                  const key_type&amp; key) const {
    return map_element_traits&lt;Elem&gt;::key(elem) &lt;
           key;
  }

  bool operator()(const key_type&amp; key,
                  const value_type&amp; elem) const {
    return key &lt;
           map_element_traits&lt;Elem&gt;::key(elem);
  }
};
</pre>

      <p>This is a generalisation of the <tt class=
      "classname">CleverLessKey</tt> class shown above. It uses the
      <tt class="methodname">key()</tt> function from the map
      element traits to ensure that the predicate class can be
      generated for any element of a map-like class and only those
      elements. A third <tt class="methodname">operator()</tt>
      overload is provided so that two elements can be compared to
      each other. We omitted the additional <tt class=
      "literal">typedef</tt>s needed for adaptability.</p>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e535" id=
        "d0e535"></a>Problem Solved! - Problem Solved?</h2>
      </div>

      <p>The code presented in the previous sections does fix all
      the imperfections in Stefan's version. At least, it
      does if you are using the GCC compiler (Code tested on gcc
      3.2 and 3.3.). But VC++ 7.1 produces an error. It turns out
      that it fails to find the <tt class=
      "classname">map_traits</tt> specialization for <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt>. The reason is related
      to <tt class="literal">const</tt> qualification. VC++ is
      happy if the <tt class="classname">map_traits</tt> template
      is specialized for <tt class="classname">const
      Pair&lt;Key,Val&gt;</tt> instead of just <tt class=
      "classname">Pair&lt;Key,Val&gt;</tt>, but that creates an
      error when compiled with GCC. We don't know yet whether
      this is because of a compiler error or because of an
      imprecision in the C++ standard. In practice, you will
      therefore have to provide both (otherwise identical)
      specializations.</p>

      <p>So here is the entire code in all its glory:</p>
      <pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;map&gt;
#include &lt;functional&gt;

// Generic map element declarations.
template&lt;typename Elem&gt; struct map_element_traits;

template&lt;typename Elem&gt; inline
const typename map_element_traits&lt;Elem&gt;::mapped_type&amp;
mapped_value(const Elem&amp; element) {
  return map_element_traits&lt;Elem&gt;::mapped_value(element);
}

template&lt;typename Elem&gt; inline
const typename map_element_traits&lt;Elem&gt;::key_type&amp;
key(const Elem&amp; element) {
  return map_element_traits&lt;Elem&gt;::key(element);
}

template&lt;typename Elem&gt;
struct key_value_compare {
  typedef typename
              map_element_traits&lt;Elem&gt;::key_type
              key_type;
  typedef typename
              map_element_traits&lt;Elem&gt;::value_type
              value_type;
  bool operator()(const value_type&amp; x,
                  const value_type&amp; y) const {
    return map_element_traits&lt;Elem&gt;::key(x) &lt;
           map_element_traits&lt;Elem&gt;::key(y);
  }

  bool operator()(const value_type&amp; elem,
                  const key_type&amp; key) const {
    return map_element_traits&lt;Elem&gt;::key(elem) &lt;
           key;
  }

  bool operator()(const key_type&amp; key,
                  const value_type&amp; elem) const {
    return key &lt;
           map_element_traits&lt;Elem&gt;::key(elem);
  }
};

// Generic map declarations.
template&lt;typename Map&gt; struct map_traits;
template&lt;typename Map&gt; inline
typename map_traits&lt;Map&gt;::const_iterator
find(const Map&amp; map,
     const typename map_traits&lt;Map&gt;::key_type&amp; key) {
  return map_traits&lt;Map&gt;::find(map, key);
}

template&lt;typename Map&gt; inline
typename map_traits&lt;Map&gt;::const_iterator
end(Map const&amp; map) {
  return map_traits&lt;Map&gt;::end(map);
}

// The lookup() function
template&lt;typename Map&gt;
const typename map_traits&lt;Map&gt;::mapped_type&amp;
lookup(const Map&amp; map,
       const typename map_traits&lt;Map&gt;::key_type&amp; target_key,
       const typename map_traits&lt;Map&gt;::mapped_type&amp; default_value) {
  typename map_traits&lt;Map&gt;::const_iterator pos
           = find(map, target_key);
  return (pos == end(map))
          ? default_value
          : mapped_value(*pos);
}

// specializations for std::map
template&lt;typename Key, typename Val&gt;
struct map_element_traits&lt; std::pair&lt;Key,Val&gt; &gt; {
  typedef std::pair&lt;Key,Val&gt; value_type;

  typedef typename value_type:: first_type key_type;
  typedef typename value_type::second_type mapped_type;

  static const key_type&amp; key(const value_type&amp; element) {
    return element.first;
  }

  static const mapped_type&amp; mapped_value(
                     const value_type&amp; element) {
    return element.second;
  }
};

template&lt;typename Key, typename T, typename Cmp, typename A&gt;
struct map_traits&lt; std::map&lt;Key,T,Cmp,A&gt; &gt; {
  typedef std::map&lt;Key,T,Cmp,A&gt; map_type;
  typedef typename map_type::key_type key_type;
  typedef typename map_type::mapped_type mapped_type;
  typedef typename map_type::value_type value_type;
  typedef typename map_type::const_iterator const_iterator;

  static const_iterator begin(const map_type&amp; map)
  { return map.begin(); }
  static const_iterator end(const map_type&amp; map)
  { return map.end(); }

  static const_iterator find(const map_type&amp; map,
                             const key_type&amp; key)
  { return map.find(key); }
};

// Our own Pair type suitable for aggregate
// initialization
template&lt;typename Key, typename Val&gt;
struct Pair {
  Key key;
  Val val;
};

// Specializations for Pair
template&lt;typename Key, typename Val&gt;
struct map_element_traits&lt; Pair&lt;Key,Val&gt; &gt; {
  typedef Pair&lt;Key,Val&gt; value_type;
  typedef Key key_type;
  typedef Val mapped_type;
  static const key_type&amp; key(
                    const value_type&amp; element)
  { return element.key; }

  static const mapped_type&amp; mapped_value(
                    const value_type&amp; element)
  { return element.val; }
};

template&lt;typename Key, typename Val, unsigned n&gt;
struct map_traits&lt; Pair&lt;Key,Val&gt;[n] &gt; { // for GCC
  typedef Key key_type;
  typedef Val mapped_type;
  typedef Pair&lt;Key,Val&gt; value_type;
  typedef const value_type* const_iterator;

  static const_iterator begin(
                 const value_type (&amp;map)[n])
  { return &amp;map[0]; }
  static const_iterator end(
                 const value_type (&amp;map)[n])
  { return &amp;map[n]; }
  static const_iterator find(
                 const value_type (&amp;map)[n],
                 const key_type&amp; target_key) {
    const_iterator i = std::lower_bound(
                 begin(map), end(map), target_key,
                 key_value_compare&lt;value_type&gt;());
    return (i == end(map) || key(*i) != target_key)
            ? end(map) : i;
  }
};

template&lt;typename Key, typename Val, unsigned n&gt;
struct map_traits&lt; const Pair&lt;Key,Val&gt;[n] &gt; {
// for VC++
  typedef Key key_type;
  typedef Val mapped_type;
  typedef Pair&lt;Key,Val&gt; value_type;
  typedef const value_type* const_iterator;
  static const_iterator begin(
               const value_type (&amp;map)[n])
  { return &amp;map[0]; }
  static const_iterator end(
               const value_type (&amp;map)[n])
  { return &amp;map[n]; }
  static const_iterator find(
               const value_type (&amp;map)[n],
               const key_type&amp; target_key) {
    const_iterator i
          = std::lower_bound(
                 begin(map), end(map), target_key,
                 key_value_compare&lt;value_type&gt;());
    return (i == end(map) || key(*i) != target_key)
            ? end(map) : i;
  }
};

// Test code
typedef const Pair&lt;int, const char*&gt; Elem;

Elem 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 substances released&quot; },
  { 32767, &quot;Game over, you lost&quot; }
};

using namespace std;

int main() {
  map&lt;int, const char*&gt; message_map;
  message_map[6]
       = &quot;Minor glitch in self-destruction module&quot;;
  const char *result
       = lookup(message_map, 6, &quot;not found&quot;);
  cout &lt;&lt; &quot;lookup(map, 6, \&quot;not found\&quot;) = &quot;
       &lt;&lt; result &lt;&lt; endl;
  result = lookup(message_map, 6, 0);
  cout &lt;&lt; &quot;lookup(map, 6, 0) = &quot; &lt;&lt; result
       &lt;&lt; endl;
  result = lookup(table, 5, &quot;not found&quot;);
  cout &lt;&lt; &quot;lookup(table, 5, \&quot;not found\&quot;) = &quot;
       &lt;&lt; result &lt;&lt; endl;
  result = lookup(table, 6, 0);
  cout &lt;&lt; &quot;lookup(table, 6, 0) = &quot;
       &lt;&lt; result
       &lt;&lt; endl;
}
</pre>
    </div>

    <div class="sect1" lang="en">
      <div class="titlepage">
        <h2><a name="d0e562" id=
        "d0e562"></a>Afterwords</h2>
      </div>

      <div class="sect2" lang="en">
        <div class="titlepage">
          <h3><a name="d0e565" id=
          "d0e565"></a>Phil's Afterword</h3>
        </div>

        <p>First, I completely agree with Stefan that C++ is too
        big, complicated and difficult to use for most programmers
        and most organisations. C++ is a great language for
        developing high quality, flexible and efficient software
        components - but (and I've said this before) most
        software is not like that.</p>

        <p>The main lesson we can take from this apparently simple
        exercise is that experience counts. I became involved in
        Stefan's problem because I felt instinctively that
        the first step should have been to <span class=
        "emphasis"><em>reduce</em></span> the number of template
        parameters, not (as Stefan tried to do) to increase it. How
        did I know this would help? I'd been there
        before.</p>

        <p>My advice to C++ programmers struggling with templates
        (or any other part of the language) is this: learn the
        rules, don't guess; don't panic; simplify the
        problem as far as you can; think carefully; experiment;
        and, finally, don't be afraid to ask for help.</p>

        <p>If there is a moral to this story I would say it is that
        software is a very young discipline. As a profession we
        still have a lot to learn. One of the problems that remains
        unsolved is how to design a programming language that is
        easy to learn, is easy to use, is applicable to a wide
        range of applications and which generates compact and
        efficient code. In my opinion, C++ is about the state of
        the art. It makes most of this possible, but it's not
        always easy.</p>

        <p>Phil Bass</p>
      </div>

      <div class="sect2" lang="en">
        <div class="titlepage">
          <h3><a name="d0e581" id=
          "d0e581"></a>Stefan's Afterword</h3>
        </div>

        <p>So we've solved all the problems. And I've
        learned a lot in the process! That's a happy end,
        isn't it?</p>

        <p>I don't think so. Look at what I wanted to achieve
        at the beginning and what we ended up with. All this is
        just a clever way to call <tt class=
        "function">std::lower_bound</tt>, isn't it? (Or the
        <tt class="methodname">find</tt> member function of
        <tt class="classname">std::map</tt>). Ok, I'm a bit
        sarcastic here.</p>

        <p>If we subtract the test code and the code related to
        <tt class="constant">std::map</tt>, which don't
        really count here, we have written in excess of 100 lines
        of source code, some of it quite tricky. And most of it is
        just the scaffolding needed to make <tt class=
        "function">std::lower_bound</tt> usable in a nice way with
        constant ROMable key/value pairs. If we include all
        compiler quirks and crappy error messages, this matter was
        suitable for filling a fair number of Overload pages.</p>

        <p>Clearly there's something amiss here. If this sort
        of thing does not get easier a lot of programmers will get
        frustrated by C++.</p>

        <p>Stefan Heinzmann</p>
      </div>

      <div class="sect2" lang="en">
        <div class="titlepage">
          <h3><a name="d0e609" id=
          "d0e609"></a>Editor's Afterword</h3>
        </div>

        <p>Reading Stefan's contributions to this issue brought
        back memories for me of an article I wrote nine years ago
        (Overload 8). There isn't space to reproduce it in this
        issue, or the editorial response it elicited (this was
        longer than the article). I won't go into the detail of the
        arguments, but just quote from the end of that
        response:</p>

        <div class="blockquote">
          <blockquote class="blockquote">
            <p>&quot;At the end of the day, I basically agree with Alan
            - C++ is harder to use than C - and I think his
            comparison between a Stylophone and a violin is well
            drawn. I don't blame the language (and I don't really
            think Alan does either) - I blame IT management for
            giving everyone a violin and saying &quot;right, now play a
            tune!&quot; What C++ highlights is the need for better
            training, better tools and more realistic
            expectations.&quot; - Sean A Corfield</p>
          </blockquote>
        </div>

        <p>Nine years have passed and nothing significant has
        changed. C++ is still to hard to use, lacks decent tools
        and expectations are seldom realistic.</p>

        <p>Alan Griffiths</p>
      </div>
    </div>

    <div class="bibliography">
      <div class="titlepage">
        <h2><a name="d0e621" id=
        "d0e621"></a>References</h2>
      </div>

      <div class="bibliomixed">
        <a name="Heinzmann" id="Heinzmann"></a>

        <p class="bibliomixed">[Heinzmann] Stefan Heinzmann:
        &#8220;The tale of a struggling template programmer&#8221;,
        this issue of <span class="citetitle"><i class=
        "citetitle">Overload</i></span></p>
      </div>

      <div class="bibliomixed">
        <a name="Vandevoorde-" id="Vandevoorde-"></a>

        <p class="bibliomixed">[Vandevoorde-] D. Vandevoorde, N. M.
        Josuttis: <span class="citetitle"><i class="citetitle">C++
        Templates: The complete guide</i></span>, Addison-Wesley
        2003</p>
      </div>

      <div class="bibliomixed">
        <a name="Sposato" id="Sposato"></a>

        <p class="bibliomixed">[Sposato] Rich Sposato: &#8220;A
        More Flexible Container&#8221;, <span class=
        "citetitle"><i class="citetitle">Overload</i></span> issue
        58 December 2003</p>
      </div>

      <div class="bibliomixed">
        <a name="comeau" id="comeau"></a>

        <p class="bibliomixed">[comeau] <span class=
        "bibliomisc"><a href="http://www.comeaucomputing.com"
        target="_top">http://www.comeaucomputing.com</a></span></p>
      </div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
