    <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's Struggles Revisited</title>
        <link>https://members.accu.org/index.php/journals/232</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>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #62 - Aug 2004 + Programming Topics</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/journals/">All</a>

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

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

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c150/">62</a>
                    (8)
<br />

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

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

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

                                            <a href="https://members.accu.org/index.php/journals/c150-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c150+65/">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's Struggles Revisited</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 August 2004 22:52:10 +01:00 or Sun, 01 August 2004 22:52:10 +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="d0e18" id="d0e18"></a></h2>
</div>
<p>Overload 61 included a couple of lengthy articles (<a href=
"#Heinzmann">Heinzmann</a>] and [<a href=
"#Heinzmann-">Heinzmann-</a>]) which demonstrated how difficult it
is to undertake a small, realistic and well defined programming
task using function templates and C++. The afterwords of the
authors and of the editor of Overload suggested that C++ is too
difficult to use.</p>
<p>The solution in the second article does indeed look verbose.
Surely, I said to myself, there must be a better way. I wondered
what I would have done if I had been faced with the same task.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e30" id="d0e30"></a>What's
Required?</h2>
</div>
<p>A lookup table.</p>
<p>My initial reaction is to just use <tt class=
"classname">std::map</tt> unless there is a good reason not to.</p>
<p>Is there a good reason not to? In this case, yes, because it is
also required to hold the table in non-volatile memory, which
requires the table to be POD (a C-style array of a C-style struct).
<tt class="classname">std::map</tt> does not fulfil this
requirement.</p>
<p>We need something that behaves like std::map but is implemented
with POD.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e47" id="d0e47"></a>First Pass:
Defining the Interface</h2>
</div>
<p>Let's borrow the bits of the interface we need from <tt class=
"classname">std::map</tt>:</p>
<pre class="programlisting">
namespace rom {
  template&lt;typename T1, typename T2&gt;
  struct pair {
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;
    T2 second;
  };

  template&lt;typename Key, typename T,
          typename Cmp = std::less&lt;Key&gt; &gt;
  class map {
  public:
    typedef Key key_type;
    typedef T mapped_type;
    typedef pair&lt;const Key, T&gt; value_type;
    typedef Cmp key_compare;
  };
}
</pre>
<p>I'm sure if I had been doing this from scratch I would have
tried to use <tt class="classname">std::pair</tt>, then realised
like Stefan that this wouldn't work because it is not an aggregate.
However I've used the hindsight I gained from reading his article
to go straight to using a pair that supports aggregate
initialisation.</p>
<p>Our new <tt class="classname">rom::map</tt> does not need a
template parameter for allocation, since the whole point of it is
that it uses a statically initialised array, so we discard that
parameter of <tt class="classname">std::map</tt>.</p>
<p>The constructor of <tt class="classname">rom::map</tt> seems to
be the obvious way to associate it with an array. The constructor
would also be an ideal place to check that the array is sorted.
Stefan used template argument deduction to obtain the size of the
array but, as this fails on some compilers, I pass the size as a
separate argument. The arguments of the constructor suggest the
member variables the class requires:</p>
<pre class="programlisting">
template&lt;typename Key, typename T,
         typename Cmp = std::less&lt;Key&gt; &gt;
class map {
public:
  typedef pair&lt;const Key, T&gt; value_type;
  map(const value_type array[],
      unsigned int array_size)
        : values(array), size(array_size) {}
private:
  const value_type * const values;
  unsigned int size;
};
</pre>
<p>The only member function we need is <tt class=
"methodname">find()</tt>. For <tt class="classname">std::map</tt>
this returns an iterator, but we can simply return a value because
we are supplying a default value to use if none can be found. At
this stage I want to verify that the interface is sound, so to get
something that I can try out as early as possible I implement
<tt class="function">find()</tt> with a linear search rather than a
more efficient binary search:</p>
<pre class="programlisting">
template&lt;typename Key, typename T,
         typename Cmp = std::less&lt;Key&gt; &gt;
class map {
public:
  const T &amp;find(const Key &amp;k, const T &amp;def) const {
    for(unsigned int n = 0; n != size; ++n) {
      if(!Cmp()(k, values[n].first)
         &amp;&amp; !Cmp()(values[n].first, k)) {
        return values[n].second;
      }
    }
    return def;
  }
};
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e90" id="d0e90"></a>Testing the
Interface</h2>
</div>
<p>Let's try it out. We know that the <tt class=
"classname">rom::map</tt> should behave like a <tt class=
"classname">std::map</tt>, so we write a utility to populate a
std::map with the same table as a rom::map and check that every
entry in the <tt class="classname">std::map</tt> can be found in
the <tt class="classname">rom::map</tt>. Additionally we check that
if an entry cannot be found in the <tt class=
"classname">rom::map</tt> the supplied default value is returned.
(For brevity, I have implemented my tests with plain C <tt class=
"literal">assert</tt>s rather than use a unit test framework.)</p>
<pre class="programlisting">
namespace {
typedef rom::map&lt;unsigned int,
                 const char *&gt; RomLookup;

RomLookup::value_type 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;}
};
typedef std::map&lt;RomLookup::key_type,
           RomLookup::mapped_type&gt; StdLookup;
void PopulateStdLookup(
         const RomLookup::value_type table[],
         unsigned int table_size,
         StdLookup &amp;stdLookup) {
  for(unsigned int n=0; n != table_size; ++n) {
    stdLookup[table[n].first] = table[n].second;
  }
}

class CheckFind {
public:
  CheckFind(const RomLookup &amp;romLookup,
            const RomLookup::mapped_type
                               &amp;def_value)
       : lookup(romLookup), def(def_value) {}
  void operator()(const StdLookup::value_type
                              &amp;value) const {
    assert(lookup.find(value.first, def)
          == value.second);
  }
private:
  const RomLookup &lookup;
  const RomLookup::mapped_type &def;
};
}
 
int main(int, char**) {
  const unsigned int table_size
            = sizeof(table)/sizeof(table[0]);
  RomLookup romLookup(table, table_size);
  StdLookup stdLookup;
  PopulateStdLookup(table, table_size,
                    stdLookup);
  std::for_each(stdLookup.begin(),
                stdLookup.end(),
                CheckFind(romLookup, 0));
  assert(romLookup.find(1, 0) == 0);
  return 0;
}
</pre>
<p>This is all fine. We have a usable interface and set of test
cases. Note that I didn't need to do any type casting to pass 0 as
the default argument to <tt class=
"methodname">romLookup.find()</tt>, it just compiled straight away
with no problems.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e120" id="d0e120"></a>Second Pass:
Implementing the Binary Search</h2>
</div>
<p>Now we need to refine <tt class="methodname">find()</tt> to use
a binary search, which requires <tt class=
"classname">std::lower_bound</tt>. My first attempt is:</p>
<pre class="programlisting">
template&lt;typename Key, typename T,
         typename Cmp = std::less&lt;Key&gt; &gt;
class map {
public:
  const T &amp;find(const Key &amp;k, const T &amp;def) const {
    const value_type *value = std::lower_bound(
             values, values+size, k, Cmp());
    if(value == values+size
       || Cmp()(k, value-&gt;first)) {
      return def;
    }
    else {
      return value-&gt;second;
    }
  }
};
</pre>
<p>This gives me a compiler error saying it can't pass <tt class=
"varname">value_type</tt>s to <tt class="function">less&lt;unsigned
int&gt;</tt>. It isn't too hard to work out that this is because I
am passing a <tt class="function">key_type</tt> comparison function
to <tt class="classname">std::lower_bound</tt> which attempts to
use it to compare <tt class="varname">value_type</tt>s. So in the
private part of the map I write a function object that adapts the
key comparison function to work with <tt class=
"varname">value_type</tt>s. Normally I do not bother to derive
private function objects from <tt class=
"function">std::unary_function</tt> or <tt class=
"function">std::binary_function</tt>, but as this raised problems
in the original article I did so on this occasion:</p>
<pre class="programlisting">
template&lt;typename Key, typename T,
         typename Cmp = std::less&lt;Key&gt; &gt;
class map {
public:
  const T &amp;find(const Key &amp;k,
                const T &amp;def) const {
    const value_type *value =
         std::lower_bound(values, values+size,
                           k, value_compare());
    // rest of member function as before
  }
private:
  struct value_compare
    : public std::binary_function&lt;value_type,
                           value_type, bool&gt; {
    bool operator()(const value_type &amp;v1,
                 const value_type &amp;v2) const {
      return Cmp()(v1.first, v2.first);
    }
  };
};
</pre>
<p>Still a compiler error, this time that I am trying to pass an
<tt class="type">unsigned int</tt> as an argument to <tt class=
"methodname">value_compare::operator()</tt>. Again, it is not too
difficult to spot that I am passing a <tt class=
"function">key_type</tt> as the third argument of <tt class=
"classname">std::lower_bound</tt> where a <tt class=
"varname">value_type</tt> is required. We use the elegant fix
employed in [<a href="#Heinzmann-">Heinzmann-</a>]:</p>
<pre class="programlisting">
template&lt;typename Key, typename T,
         typename Cmp = std::less&lt;Key&gt; &gt;
class map {
public:
  const T &amp;find(const Key &amp;k,
                const T &amp;def) const {
    const value_type key = { k };
    const value_type *value =
       std::lower_bound(values, values+size,
                        key, value_compare());
    // rest of member function as before
  }
};
</pre>
<p>Now everything compiles cleanly (including the use of <tt class=
"classname">std::binary_function</tt>) and the test code also
executes successfully.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e188" id="d0e188"></a>Third Pass:
Considering the Disadvantages</h2>
</div>
<p>We have reached a solution that works. We reached it by a less
painful route, with less code and with simpler code. But does this
solution have some disadvantages the original did not have?</p>
<p>Most obviously, it does not provide a mechanism that can be used
equally well for any map-like container: it is a less general
solution. I'm not convinced this is a disadvantage. &quot;Why restrict
ourselves to arrays?&quot; asks [<a href="#Heinzmann-">Heinzmann-</a>].
I'm tempted to reply &quot;Why not?&quot;</p>
<p>Another difference is that our <tt class=
"classname">rom::map</tt>s have two member variables that take up
memory which the original solution did not. This may be
insignificant, but since the context of the task is an embedded
system it is conceivable that we may be required to conserve
memory. If this is the case there is a simple refactoring that can
be applied to the <tt class="classname">rom::map</tt>. The array
can be passed directly to the <tt class="methodname">find()</tt>
member function, which can be made static, and the constructor and
member variables removed. (If we had implemented a check that the
array is sorted in the constructor, that code could also be
refactored into a static member function).</p>
<p>At this stage, if I had a smart enough compiler, I could try to
use template argument deduction to determine the array size rather
than pass it as an explicit parameter. Personally, I don't think I
would go to that trouble.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e211" id="d0e211"></a>Fourth Pass:
Things Get Nasty</h2>
</div>
<p>If we find it necessary to eliminate the constructor and member
variables, leaving only a static member function, the next obvious
refactoring is to turn it into a standalone function. But if we do
that, we run into the problems experienced in [<a href=
"#Heinzmann">Heinzmann</a>]. So we are faced with a choice: proceed
with the refactoring and introduce the necessary traits class as in
[<a href="#Heinzmann-">Heinzmann-</a>], or abandon the refactoring
and stick with what we have. I'd go for the latter. The syntax is a
little less elegant, but overall it's simpler.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e222" id=
"d0e222"></a>Conclusion</h2>
</div>
<p>Why did things run more smoothly with the approach I took? It is
because my solution uses a class template rather than a function
template. It therefore does much less template argument deduction,
which avoids a whole host of problems.</p>
<p>This suggests a design guideline: if you are struggling to
implement a function template, consider re-implementing it as a
class template (as an alternative to introducing traits).</p>
<p><span class="emphasis"><em>Chris Main</em></span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e232" id=
"d0e232"></a>Afterword</h2>
</div>
<p>Is C++ too difficult? I'm not so sure. I think I've demonstrated
that the code which provoked comments to that effect was
unnecessarily complicated. I think I did so not because I am a C++
expert but because I followed strategies that are generally useful
when programming: follow the pattern of a known working solution to
a similar problem (in this case <tt class=
"classname">std::map</tt>), work incrementally towards the
solution, try to keep things as simple as possible.</p>
<p>How would the problem be solved in other programming languages?
In C you could use the standard library <tt class=
"function">bsearch()</tt>. I have used it, but it is quite fiddly
to get the casting to and from <tt class="type">void *</tt> right,
so in my experience it is not significantly easier to use than C++.
What other languages could be used?</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e248" id="d0e248"></a>References</h2>
</div>
<div class="bibliomixed"><a name="Heinzmann" id="Heinzmann"></a>
<p class="bibliomixed">[Heinzmann] S. Heinzmann, &quot;The Tale of a
Struggling Template Programmer&quot;, <span class="citetitle"><i class=
"citetitle">Overload 61</i></span>, June 2004</p>
</div>
<div class="bibliomixed"><a name="Heinzmann-" id="Heinzmann-"></a>
<p class="bibliomixed">[Heinzmann-] S. Heinzmann and P. Bass, &quot;A
Template Programmer's Struggles Resolved&quot;, <span class=
"citetitle"><i class="citetitle">Overload 61</i></span>, June
2004</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
