    <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(s)</title>
        <link>https://members.accu.org/index.php/articles/317</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 #59 - Feb 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/c153/">59</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+153/">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(s)</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 02 February 2004 21:55:35 +00:00 or Mon, 02 February 2004 21:55:35 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
<h3>Regarding &quot;A more flexible container&quot; by
Rich Sposato, Overload 58 (December 2003)</h3>
</div>
<p>Although it is certainly interesting to consider alternative
implementations of standard containers, I think Rich has chosen the
wrong solution to the problem.</p>
<p>What he want to do is to extract all members of a collection
satisfying a given condition. In his driving example, he has a set
of Employee records, and he wants to extract those elements of the
container that matches a given surname, say. If one only ever wants
to deal with sets of such records, Rich's solution is probably the
best one can do. But if one later wants, as Rich does in the
article, to perform a similar operation on another type of
container, the limitations of his approach become clear.</p>
<p>Instead of modifying each container by defining a new one built
upon the standard containers, it is much better to have a generic
algorithm working with any container (standard or not).</p>
<p>So it seems to me, a better, or at least more generic, solution
would be to define an algorithm working roughly like this:</p>
<pre class="programlisting">
result = filter(collection,comparator);
  // filter elements of a container
</pre>
<p>where <tt class="computeroutput">result</tt> and <tt class=
"computeroutput">collection</tt> are containers of the same kind
and <tt class="computeroutput">comparator</tt> is a function, or
functor, taking an element and returning a Boolean value.</p>
<p>A template version would look something like this (in pseudo-
C++ to show the structure more clearly)</p>
<pre class="programlisting">
template&lt;class Coll, class Comp&gt;
Coll filter(Coll coll, Comp cmp) {
  Coll res(0); // create empty result set
  for (iterator it=coll.begin();
       it != coll.end();
       ++it)
    if (cmp(it))
      res.insert(it);
  return res;
}
</pre>
<p>This will then work for any container having a standard iterator
interface and an <tt class="computeroutput">insert()</tt> member
function as well as for any <tt class="computeroutput">cmp</tt>
having an <tt class="computeroutput">operator()</tt> defined taking
a container element of the right type as argument and returning
something which can be interpreted as a Boolean.</p>
<p>All the extra work now goes into defining the comparator
function or functor, which is probably precisely where the effort
should be concentrated anyway.</p>
<p>While this solution is simpler and more generic than Rich's, it
is not purely object oriented. In fact, it wouldn't be possible to
carry it over directly to Java or C#. Instead, it is an example of
what one might call a &quot;functional programming design pattern&quot;. The
filter algorithm above is a C++ analogue of a so-called &quot;higher
order function&quot; in functional programming (FP), i.e. a function
taking another function as argument. Actually, very often OOP
design patterns can be translated into FP higher order
functions.</p>
<p>The particular higher order function used here, filter, exists
in all major FP languages (Lisp, Haskell, ML) and in some other
multi-paradigm ones (Perl, Python).</p>
<p>What this illustrates is the idea that, however powerful a
concept, OOP just isn't the right solution in all circumstances.
Luckily, C++ is a multi-paradigm language, supporting not just OOP
and C-style procedural programming, but also FP-style programming
as above. That being said, C++ has a very, very strong support for
efficient OOP code, allowing most compilers to make very efficient
assembler code. In contrast, the FP-aspects, although introduced
with the STL, have received less attention, and not all compilers
will generate efficient code in these cases. This, however, may be
compensated by the optimisations made for the standard
containers.</p>
<p>On the other hand, such an FP-like solution is easier to
maintain, the code is concentrated in one place instead of being
duplicated in all containers. Moreover, the FP-like solution above
is more generic. Suppose, for instance, that you defined an
iterator interface for files, with the &quot;elements&quot; being the
individual lines. The filter algorithm can then be turned into a
utility like UNIX's grep, extracting lines meeting a specific
criterion.</p>
<p>Whether to put something into a member function or not is a
difficult question to answer in general. All sorts of issues may be
involved: design principles, maintainability, and efficiency etc.
My own pragmatic rule of thumb is, if the same code is copied with
very little change in many classes, it is probably worth
considering putting it outside, either in a special class or as an
algorithm.</p>
<div class="sidebar">
<p class="title c3">Rich Sposato's Reply</p>
<p>My article had two purposes. One was to create associative
containers that allow searching using a type other than the key
type. The other goal was to remove the unnecessary objects used to
search through the standard associative containers. Creating a
generic algorithm to find all elements of any container type that
satisfy a predicate was not my intention. Indeed, such an algorithm
is missing from the STL, but I will get to that later. First, let
us look at the associative containers and the generic search
algorithms.</p>
<p>The STL's stand-alone search (<tt class=
"computeroutput">binary_search</tt>, <tt class=
"computeroutput">lower_bound</tt>, <tt class=
"computeroutput">upper_bound</tt>, and <tt class=
"computeroutput">equal_range</tt>) algorithms provide logarithmic
complexity only for random-access iterators, and linear complexity
for all other iterator types. The standard associative containers
are typically implemented using red-black binary trees, and with
their bi-directional iterators, they are not served well by these
functions. I find it ironic that associative containers were
designed for logarithmic complexity but their iterators only
provide linear complexity with the STL algorithm functions, while
three of the sequential containers (<tt class=
"computeroutput">vector</tt>, <tt class=
"computeroutput">string</tt>, and <tt class=
"computeroutput">deque</tt>) have a linear internal arrangement,
but their iterators provide logarithmic complexity with the same
STL algorithms. The STL's stand-alone <tt class=
"computeroutput">count</tt> and <tt class=
"computeroutput">find</tt> functions provide linear complexity for
all iterator types. So that irony does not apply to these
functions.</p>
<p>These associative containers have their own <tt class=
"computeroutput">find</tt>, <tt class="computeroutput">count</tt>,
<tt class="computeroutput">lower_bound</tt>, <tt class=
"computeroutput">upper_bound</tt>, and <tt class=
"computeroutput">equal_range</tt> member functions, because as
members, they can use the internal structure of the containers to
provide greater efficiency than linear complexity. The <tt class=
"computeroutput">set</tt>'s operations require only logarithmic
complexity. These functions should be used instead of the generic
stand-alone functions by the same names. (See item #44 in Scott
Meyer's book: &quot;Effective STL&quot;.)</p>
<p>Frank Antonsen's example for filtering elements from a container
is not the most generic solution for C++. His filter function
requires the collection to have a constructor that accepts a single
integer parameter; a constraint not met by five STL containers.
This example is not truly container-independent code. (See item #2
in Scott Meyer's book: &quot;Effective STL&quot;.) By acting on a container
rather than an iterator, the filter will not work with arrays - a
requirement of the STL algorithms. This points out another irony:
algorithms that act only on iterators are more likely to provide
&quot;container-independent&quot; code than algorithms that act on
containers. As Raoul Gough eloquently explained in his article
(&quot;Choosing Template Parameters&quot; also in Overload issue #58),
picking the correct template parameter types can make all the
difference between a flexible and inflexible class or function.</p>
<p>Using the <tt class="computeroutput">std::copy</tt> function as
an example, we can make a generic filter named <tt class=
"computeroutput">copy_if</tt> that uses a predicate. The filtering
function will accept an iterator type as a template parameter, and
use the <tt class="computeroutput">typename</tt> keyword instead of
the class keyword within the template specification. Since
<tt class="computeroutput">copy_if</tt> will always have linear
complexity no matter which type of iterator or container uses it,
developers might be better off using <tt class=
"computeroutput">std::set::equal_range</tt> and then calling
<tt class="computeroutput">std::copy</tt>. The <tt class=
"computeroutput">copy_if</tt> algorithm fulfills all the abilities
of Frank's filter function with fewer constraints.</p>
<p>The <tt class="computeroutput">copy</tt> function's signature
is:</p>
<pre class="programlisting">
template&lt; typename InputIter,
          typename OutputIter &gt;
OutputIter copy(InputIter first,
                const InputIter&amp; last,
                OutputIter output );
</pre>
<p>The <tt class="computeroutput">copy_if</tt> function would have
a signature of:</p>
<pre class="programlisting">
template&lt; typename InputIter,
          typename OutputIter,
          typename Predicate &gt;
OutputIter copy_if(InputIter first,
                   const InputIter&amp; last,
                   OutputIter output,
                   Predicate pred );
</pre>
<p>Alas, the STL has no <tt class="computeroutput">copy_if</tt>
function, although it has <tt class="computeroutput">copy</tt> and
<tt class="computeroutput">copy_backward</tt>. This omission
becomes more obvious when considering that other functions such as
<tt class="computeroutput">find</tt>, <tt class=
"computeroutput">count</tt>, <tt class=
"computeroutput">remove</tt>, and <tt class=
"computeroutput">remove_copy</tt> have predicated versions named
<tt class="computeroutput">find_if</tt>, <tt class=
"computeroutput">count_if</tt>, <tt class=
"computeroutput">remove_if</tt>, and <tt class=
"computeroutput">remove_copy_if</tt>. The implementation for
<tt class="computeroutput">copy_if</tt> is trivial, and in a time
honoured tradition, I shall leave that as an exercise to the
reader.</p>
<p>Other languages may have filter functions that act as Frank
described them, but my article was not about making generic filters
for C++ or any other language.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
