    <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  :: Implementing the Bridge pattern using templates with
Microsoft Visual C++ 6.0</title>
        <link>https://members.accu.org/index.php/articles/362</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 #54 - Apr 2003</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/c157/">54</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+157/">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;Implementing the Bridge pattern using templates with
Microsoft Visual C++ 6.0</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 02 April 2003 22:57:19 +01:00 or Wed, 02 April 2003 22:57:19 +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>I wonder whether you had a similar experience to me. You read
with excitement Andrei Alexandrescu's Modern C++ Design [<a href=
"#Alexandrescu">Alexandrescu</a>] (the author's remark &quot;Truly there
is beauty in computer engineering&quot; could be applied to his own
book). Then you came up against Microsoft Visual C++ at your place
of work and found you couldn't try much of it out. Do we have to be
content with using all that fun template stuff on our home
computers, where we get to choose the compiler, or can we use some
of the techniques even with Visual C++?</p>
<p>The main limitation of Visual C++ 6.0 is its lack of support for
partial specialisation of class templates. That eliminates using
Alexandrescu's TypeLists, upon which a significant portion of his
book depends. Another limitation is that it does not permit
template parameters that are themselves class templates. This is
less of a problem since the inferior alternative of member function
templates is supported (though the implementation of such functions
has to be placed in the class definition, &quot;inline&quot; style). Within
the boundaries set by these limitations there are some valuable
techniques available to us as I hope to demonstrate.</p>
<p>The example I have chosen is to implement the Bridge pattern
[<a href="#Gamma-et-al">Gamma-et-al</a>] for a class by making the
class of its implementation member variable a policy class, passed
as a template parameter. This application of templates was
mentioned by Nicolai Josuttis in his talk at the 2001 ACCU
Conference (a talk described in C Vu as &quot;solid but uninspiring&quot;.
Well, I was inspired by it!). I am also indebted in what follows to
Lois Goldthwaite's stimulating presentation of polymorphism using
templates in Overload [<a href="#Goldthwaite">Goldthwaite</a>].</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e33" id="d0e33"></a>The example
class</h2>
</div>
<p>To be specific, I am going to develop a Blackjack Hand class, as
suggested by Code Critique 14 [<a href="#CVu14.1">CVu14.1</a>]. For
card names I will use a simple enum:</p>
<pre class="programlisting">
// card.h (include guard not shown)
namespace Blackjack {
  enum Card { ace, king, queen, jack, ten,
              nine, eight, seven, six,
              five, four, three, two };
}
</pre>
<p>I will also use an encapsulated lookup table of card values:</p>
<pre class="programlisting">
// card_values.h (include guard not shown)
#include &lt;map&gt;
#include &lt;exception&gt;
#include &quot;card.h&quot;

namespace Blackjack {
  class Card_Values {
  public:
    explicit Card_Values(unsigned int
                         ace_value = 1);
    // copy constructor, assignment, swap,
    // destructor not shown

    class Card_Has_No_Value
         : public std::exception {};
    unsigned int lookup(Card card) const
         throw(Card_Has_No_Value);
  private:
    typedef std::map&lt;Card, unsigned int&gt;
                           Card_Lookup;
    Card_Lookup card_lookup;
  };
}
</pre>
<p>For a first pass, we build a non-template version of the Hand
class:</p>
<pre class="programlisting">
// hand.h (include guard not shown)
#include &quot;card.h&quot;
#include &lt;map&gt;
#include &lt;exception&gt;

namespace Blackjack {
  class Hand {
  public:
    // default constructor, copy constructor,
    // assignment, swap and destructor not shown
    class Four_Of_That_Card_Already
             : public std::exception {};
    class Five_Cards_Already
             : public std::exception {};
    class Fewer_Than_Two_Cards
             : public std::exception {};
    Hand&amp; add(Card card)
             throw(Four_Of_That_Card_Already,
    Five_Cards_Already);
    unsigned int value() const
             throw(Fewer_Than_Two_Cards);
  private:
    struct Card_Data {
       unsigned int count;
    };
    typedef std::map&lt;Card, Card_Data&gt;
    Card_Container;
    Card_Container cards;
    unsigned int number_of_cards;
    class Accumulate_Card_Value;
  };
}

// hand.cpp
#include &quot;hand.h&quot;
#include &quot;card_values.h&quot;
#include &lt;numeric&gt;

namespace {
  const Blackjack::Card_Values&amp;
             get_card_values() {
  static const Blackjack::Card_Values
             card_values;
  return card_values;
}

class Blackjack::Hand::Accumulate_Card_Value {
  public:
    Accumulate_Card_Value(
             const Card_Values&amp; card_values)
             : values(card_values) {}
    unsigned int operator()(
      unsigned int accumulated_value,
      const Card_Container::value_type&amp;
             card_data) {
      return accumulated_value +=
             (card_data.second.count *
             values.lookup(card_data.first));
    }
  private:
    const Card_Values&amp; values;
  };
}

// default constructor, copy constructor,
// assignment, swap and destructor not shown

Blackjack::Hand::AddStatus
Blackjack::Hand::add(Card card)
            throw(Four_Of_That_Card_Already,
                  Five_Cards_Already) {
  if(number_of_cards == 5) {
    throw Five_Cards_Already();
  }
  Card_Data&amp; card_data = cards[card];
  if(card_data.count == 4) {
    throw Four_Of_That_Card_Already();
  }
  ++card_data.count;
  ++number_of_cards;
  return *this;
}

unsigned int Blackjack::Hand::value() const
             throw(Fewer_Than_Two_Cards) {
  if(number_of_cards &lt; 2) {
    throw Fewer_Than_Two_Cards();
  }
  unsigned int hand_value =
             std::accumulate(cards.begin(),
             cards.end(),
             0,
             Accumulate_Card_Value(
               get_card_values()));
  if( (hand_value &lt; 12) &amp;&amp;
      (cards.find(ace) != cards.end()) ) {
    hand_value += 10;
  }
  return hand_value;
}
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e51" id="d0e51"></a>Converting the
example class to a template</h2>
</div>
<p>In the non-template version, the implementation of hand is hard
coded to be a <tt class="literal">std::map&lt;Card,
Card_Data&gt;</tt> together with a cached value <tt class=
"varname">number_of_cards</tt>. Our goal is to replace this
implementation with a single member variable.The class of this
member variable will be a template parameter. To reach this goal we
need to identify all the places in the implementation of Hand that
will depend upon that member variable. To simplify matters we make
the reasonable assumption that the class of the member variable
will always have the properties of an STL container, i.e. we can
assume things like <tt class="methodname">size()</tt> and iterators
are always available. In <tt class="methodname">add()</tt> we
additionally need to obtain non-const references to the count for a
given card and to the total number of cards in the hand. In
<tt class="methodname">value()</tt> we need to determine the total
number of cards in the hand and whether the container contains an
ace. We can turn these four requirements into helper function
templates. Function templates are particularly useful because of
the way C++ deduces the instantiation required from the function
arguments, avoiding the need for explicit instantiations.</p>
<pre class="programlisting">
// hand_implementation.h (include guard not
// shown)
#include &quot;card.h&quot;

namespace Blackjack {
  // Assume that Card_Container is usually a
  // std::map If something else is used,
  // e.g. std::vector, these function
  // templates would need to be specialised to
  // use std::find

  template&lt; class Card_Container &gt;
  unsigned int&amp; hand_implementation_count(
              Card card,
              Card_Container&amp; card_container) {
    return card_container[card].count;
  }

  template&lt; class Card_Container &gt;
  typename Card_Container::const_iterator
  hand_implementation_find(
              Card card,
              const Card_Container&amp;
              card_container) {
    return card_container.find(card);
  }

  // non-const reference version of
  // number_of_cards
  template&lt; class Card_Container &gt;
  unsigned int&amp;
      hand_implementation_number_of_cards
             (Card_Container&amp; card_container) {
    return card_container.number_of_cards;
  }

  // const version of number_of_cards
  template&lt; class Card_Container &gt;
  unsigned int
      hand_implementation_number_of_cards
             (const Card_Container&amp;
             card_container) {
    return card_container.number_of_cards;
  }
}
</pre>
<p>Less obviously, perhaps, <tt class=
"literal">Accumulate_Card_Value</tt> depends upon the type of
values contained by the container, so is indirectly dependent upon
the container. We therefore make it a nested class of the container
like so:</p>
<pre class="programlisting">
// card_count_container.h (include guard not
// shown)
#include &lt;map&gt;
#include &quot;card.h&quot;
#include &quot;card_values.h&quot;

namespace Blackjack {
  struct Card_Count {
    unsigned int count;
    Card_Count() : count(0) {}
  };

  class Card_Count_Container
        : public std::map&lt;Card, Card_Count&gt; {
  public:
    unsigned int number_of_cards;
    // cached value as before
    class Accumulate_Card_Value {
      // same as before
    };
  };
}
</pre>
<p>We are now in a position to re-implement Hand as a class
template. I follow the convention described by Dietmar Kuehl at the
2002 ACCU Conference of placing the implementation of the class
template in a <tt class="literal">.tpp</tt> file. For this article
I am going to put all the instantiations in a <tt class=
"literal">.cpp</tt> file in which this <tt class=
"literal">.tpp</tt> file is included. The alternative is to let
clients include the <tt class="literal">.tpp</tt> file and perform
the instantiations themselves. The <tt class="literal">.tpp</tt>
file serves to keep both of these alternatives available to us.</p>
<pre class="programlisting">
// hand_type.h (include guard not shown)
#include &quot;card.h&quot;
#include &quot;card_count_container.h&quot;

namespace Blackjack {
  // Exceptions moved out of class into
  // namespace so that all instantiations
  // can share the exceptions
  class Four_Of_That_Card_Already
            : public std::exception {};
  class Five_Cards_Already
            : public std::exception {};
  class Fewer_Than_Two_Cards
            : public std::exception {};
  template&lt; class Card_Container &gt;
  class Hand_Type {
  public:
    // identical to public section of
    // non-template Hand class except
    // for exceptions as noted above
  protected:
    // get_card_values() is moved here in
    // case we want to provide the
    // implementation of this class template
    // in a header file
    const Card_Values&amp; get_card_values() const;
  private:
    Card_Container cards;
  };

  // declare the valid instantiations
  typedef Hand_Type&lt;Card_Count_Container&gt;
                           Hand_No_Cached_Values;
}

// hand_type.tpp
#include &quot;card_values.h&quot;
#include &quot;hand_implementation.h&quot;
#include &lt;numeric&gt;

// default constructor, copy constructor,
// assignment, swap and destructor not
// shown
template&lt; class Card_Container &gt;
Blackjack::Hand_Type&lt;Card_Container&gt;::Hand_Type&amp;
Blackjack::Hand_Type&lt;Card_Container&gt;::add(
                                     Card card)
         throw(Four_Of_That_Card_Already,
               Five_Cards_Already) {
  // use the helper to access the number of
  // cards
  unsigned int&amp; number_of_cards =
    hand_implementation_number_of_cards(
                              cards);
  if(number_of_cards == 5) {
    throw Five_Cards_Already();
  }
  // use the helper to access the count
  unsigned int&amp; count =
    hand_implementation_count(card, cards);
  if(count == 4) {
    throw Four_Of_That_Card_Already();
  }
  ++count;
  ++number_of_cards;
  return *this;
}

template&lt; class Card_Container &gt;
unsigned int Blackjack::Hand_Type&lt;
                 Card_Container&gt;::value() const
       throw(Fewer_Than_Two_Cards) {
  // use the helper to check the number of
  // cards
  if(hand_implementation_number_of_cards(
                              cards) &lt; 2) {
    throw Fewer_Than_Two_Cards();
  }

  unsigned int hand_value =
    std::accumulate(
         cards.begin(),
         cards.end(),
         0,
         typename Card_Container::
              Accumulate_Card_Value(
                     get_card_values()));
  if( (hand_value &lt; 12) &amp;&amp;
      // use the helper to check for an ace
      (hand_implementation_find(ace, cards)
              != cards.end()) ) {
    hand_value += 10;
  }
  return hand_value;
}

template&lt; class Card_Container &gt;
const Blackjack::Card_Values&amp;
    Blackjack::Hand&lt;Card_Container&gt;::
                   get_card_values() const {
  static const Card_Values card_values;
  return card_values;
}

// hand_type.cpp
#include &quot;hand_type.h&quot;
#include &quot;hand_type.tpp&quot;
#include &quot;card_count_container.h&quot;

// instantiate the valid instantiations
template
Blackjack::Hand_Type&lt;
              Blackjack::Card_Count_Container&gt;;
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e99" id="d0e99"></a>Creating a
different instantiation of the class template</h2>
</div>
<p>So far so good, but we only have one instantiation at the
moment. It may appear, therefore, that we haven't gained very much.
In fact we have significantly improved the testability of the
<tt class="classname">Hand</tt> class, a point to which I will
return later.</p>
<p>Let's try and build a variant of Hand that looks up the value of
a card when it is added to the hand, and caches that value. For
this we need an additional helper function template that will set
the value for a card. We need to specialise this new function
template to do nothing when there is nowhere to cache the value
(which is the case for our first instantiation). Hence:</p>
<pre class="programlisting">
// hand_implementation.h (include guard not
// shown)
#include &quot;card.h&quot;
#include &quot;card_count_container.h&quot;

namespace Blackjack {
  // hand_implementation_count(),
  // hand_implementation_find()
  // and
  // hand_implementation_number_of_cards()
  // as before
  template&lt; class Card_Container &gt;
  void hand_implementation_set_value(
                       Card card,
                       unsigned int value,
                       Card_Container&amp; card_container) {
    card_container[card].value = value;
  }

  // specialisation to do nothing when there
  // is nowhere to cache the value
  template&lt;&gt;
  void hand_implementation_set_value(
                       Card card,
                       unsigned int value,
                       Card_Count_Container&amp; card_container);
}

// hand_implementation.cpp
#include &quot;hand_implementation.h&quot;

template &lt;&gt;
void Blackjack::hand_implementation_set_value
                      (Card card,
                      unsigned int value,
                      Card_Count_Container&amp; card_container) {}
</pre>
<p>The container class is:</p>
<pre class="programlisting">
// card_count_with_value_container.h
// (include guard not shown)
#include &quot;card_count_container.h&quot;

namespace Blackjack {
  struct Card_Count_With_Value
           : public Card_Count {
    unsigned int value;
    Card_Count_With_Value() : value(0){}
  };

  class Card_Count_With_Value_Container
           : public std::map&lt;Card,
                    Card_Count_With_Value&gt; {
  public:
    unsigned int number_of_cards; // as before
    class Accumulate_Card_Value {
    public:
      Accumulate_Card_Value(
             const Card_Values&amp; /* unused */) {}
      unsigned int operator()
             (unsigned int accumulated_value,
             const std::map&lt;Card,
             Card_Count_With_Value&gt;::value_type&amp;
                          card_data) {
        return accumulated_value +=
             (card_data.second.count *
             card_data.second.value);
      }
    };
  };
}
</pre>
<p>Notice that we have adjusted <tt class=
"function">Accumulate_Card_Value operator()</tt> to take advantage
of the cached values; the signature of its constructor is
preserved, even though the <i class=
"parameter"><tt>Card_Values</tt></i> argument is unused, so that it
will work with the <tt class="classname">Hand_Type</tt> we have
already. We then modify <tt class=
"methodname">Hand_Type::add()</tt> to call <tt class=
"function">hand_implementation_set_value()</tt> at the appropriate
point:</p>
<pre class="programlisting">
template&lt; class Card_Container &gt;
Blackjack::Hand_Type&lt;Card_Container&gt;::Hand_Type&amp;
  Blackjack::Hand_Type&lt;Card_Container&gt;::add(
                                      Card card)
                throw(Four_Of_That_Card_Already,
                      Five_Cards_Already) {
    unsigned int&amp; number_of_cards =
      hand_implementation_number_of_cards(cards);
    if(number_of_cards == 5) {
      throw Five_Cards_Already();
    } 
    unsigned int&amp; count =
      hand_implementation_count(card, cards);
    if(count == 4) {
      throw Four_Of_That_Card_Already();
    }
    if(count == 0) {
      // use the helper to cache the card value
      hand_implementation_set_value(card,
                 get_card_values().lookup(card),
                 cards);
    }
    ++count;
    ++number_of_cards;
    return *this;
  }
</pre>
<p>We add the new instantiations:</p>
<pre class="programlisting">
// in hand_type.h
typedef
  Hand_Type&lt;Card_Count_With_Value_Container&gt;
  Hand_With_Cached_Values;
  // in hand_type.cpp
template Blackjack::Hand_Type&lt;
  Blackjack::Card_Count_With_Value_Container&gt;;
</pre>
<p>I have used long names for the instantiation typedefs in an
attempt to document the characteristics of each variant. I am
assuming that any particular client is likely to want only one
variant, and will further typedef the variant required to a shorter
name like <tt class="literal">Hand</tt>. (I have used <tt class=
"literal">Hand_Type</tt> for the class template so that the simple
name <tt class="literal">Hand</tt> is available for clients to
use).</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e149" id="d0e149"></a>Making the
implementation member variable a pointer</h2>
</div>
<p>The classic Bridge pattern, of course, has the implementation
member variable as a pointer. This allows us to change the
implementation without forcing clients to recompile. We cannot
simply instantiate our existing <tt class="literal">Hand_Type</tt>
with a pointer because its implementation does not dereference the
member variable cards. The ideal solution would be to partially
specialise <tt class="literal">Hand_Type</tt> for all
instantiations taking a pointer as the template parameter, but this
is not supported by Visual C++ 6.0. The workaround is to define
another class template which I will name <tt class=
"literal">Hand_Bridge</tt>.</p>
<p>Bjarne Stroustrup [<a href="#Stroustrup">Stroustrup</a>] writes
that this was the approach he tried before deciding upon partial
specialisation. He comments that he abandoned it because even good
programmers forgot to use the templates designed to be instantiated
with pointers. That problem does not arise in our case, though,
because the compiler prevents us from instantiating <tt class=
"literal">Hand_Type</tt> with a pointer.</p>
<p>For this class template I will assume the existence of a
suitable smart pointer (deep copy is appropriate - see Alexandrescu
[<a href="#Alexandrescu">Alexandrescu</a>] for a full discussion of
smart pointers):</p>
<pre class="programlisting">
// hand_bridge.h (include guard not shown)
#include &quot;card.h&quot;
#include &quot;smart_pointer.h&quot;

namespace Blackjack {
  template&lt; class Card_Container &gt;
  class Hand_Bridge {
  public:
    // identical to public section of
    // Hand_Type class
  private:
    Smart_Pointer&lt;Card_Container&gt; cards;
  };

  // Forward declaration is now sufficient in
  // the header
  class Card_Container_Implementation;
  // declare the valid instantiation
  typedef Hand_Bridge&lt;
          Card_Container_Implementation&gt; Hand;
}

// hand_bridge.tpp
#include &quot;card_values.h&quot;
#include &quot;hand_implementation.h&quot;
#include &lt;numeric&gt;

// default constructor, copy constructor,
// assignment, swap and destructor not shown
template&lt; class Card_Container &gt;
Blackjack::Hand_Bridge&lt;Card_Container&gt;::
    Hand_Bridge&amp; Blackjack::Hand_Bridge&lt;
        Card_Container&gt;::add(Card card)
            throw(Four_Of_That_Card_Already,
                  Five_Cards_Already) {
  unsigned int&amp; number_of_cards =
      hand_implementation_number_of_cards(
          cards-&gt;implementation());
  if(number_of_cards == 5) {
    throw Five_Cards_Already();
  }
  unsigned int&amp; count = hand_implementation_count(
      card, cards-&gt;implementation());
  if(count == 4) {
    throw Four_Of_That_Card_Already();
  }
  if(count == 0) {
    hand_implementation_set_value(card,
        get_card_values().lookup(card),
    cards-&gt;implementation());
  }
  ++count;
  ++number_of_cards;
  return *this;
}

template&lt; class Card_Container &gt;
unsigned int Blackjack::Hand_Bridge&lt;
    Card_Container&gt;::value() const
      throw (Fewer_Than_Two_Cards) {
  if(hand_implementation_number_of_cards(
      cards-&gt;const_implementation()) &lt; 2) {
    throw Fewer_Than_Two_Cards();
  }
  unsigned int hand_value =
      std::accumulate(cards-&gt;begin(),
           cards-&gt;end(), 0, typename
  Card_Container::Accumulate_Card_Value(
       get_card_values()));
  if( (hand_value &lt; 12) &amp;&amp;
      (hand_implementation_find(ace,
          cards-&gt;const_implementation()) !=
              cards-&gt;end()) ) {
    hand_value += 10;
  }
  return hand_value;
}


//hand_bridge.cpp
#include &quot;hand_bridge.h&quot;
#include &quot;hand_bridge.tpp&quot;
#include &quot;card_count_container.h&quot;
#include &quot;card_count_with_value_container.h&quot;

namespace {
  template&lt; class Card_Container &gt;
  class Implementation : public Card_Container {
  public:
    Card_Container&amp; implementation() {
      return *this;
    }
    const Card_Container&amp;
    const_implementation() const {
      return *this;
    }
  };
}

#ifdef NO_CACHED_CARD_VALUES
class Blackjack::Card_Container_Implementation
    : public Implementation&lt;
         Blackjack::Card_Count_Container&gt; {};
#else // use the implementation with cached
      // card values
class Blackjack::Card_Container_Implementation
    : public Implementation&lt;Blackjack::
        Card_Count_With_Value_Container&gt; {};
#endif // NO_CACHED_CARD_VALUES

// instantiate the valid instantiation template
Blackjack::Hand_Bridge&lt;
    Blackjack::Card_Container_Implementation&gt;;
</pre>
<p>We can switch the implementation of Hand simply by recompiling
<tt class="filename">hand_bridge.cpp</tt> with or without
<tt class="literal">NO_CACHED_CARD_VALUES</tt> being defined;
clients of <tt class="literal">Hand</tt> do not need to be
recompiled.</p>
<p>You will no doubt be wondering why I have found it necessary to
derive <tt class="literal">Card_Container_Implementation</tt> from
the helper class template Implementation. The reason is so that the
specialisations of the helper function templates are used. Take for
example <tt class="function">hand_implementation_set_value()</tt>.
This has a specialisation for <tt class=
"literal">Card_Count_Container</tt>. If we simply called <tt class=
"function">hand_implementation_set_value(*cards)</tt> the type of
<tt class="literal">*cards</tt> is <tt class=
"literal">Card_Container_Implementation</tt> for which there is no
specialisation (nor can there be since this is the class that
changes depending upon our compilation settings); the compiler
tries to use the unspecialised function template and fails to
compile if <tt class="literal">NO_CACHED_CARD_VALUES</tt> is
defined. In contrast, when we call <tt class=
"literal">hand_implementation_set_value(cards-&gt;
implementation())</tt> the type of <tt class="literal">cards-&gt;
implementation()</tt> is <tt class=
"literal">Card_Count_Container</tt> (if <tt class=
"literal">NO_CACHED_CARD_VALUES</tt> is defined) and the compiler
uses the specialised function template as required.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e224" id="d0e224"></a>Testing using
the Dependency Inversion Principle revisited</h2>
</div>
<p>Implementing the Bridge pattern in the way I have described has
the benefit of facilitating unit testing. It realises the
Dependency Inversion Principle [<a href="#DIP">DIP</a>] because
classes depend upon other classes only via template parameters. It
is therefore easy to use stub versions of classes that a class
under test depends upon: the class under test is simply
instantiated with the stub. I believe that this realisation of the
Dependency Inversion Principle by means of templates is an
improvement upon the realisation using abstract base classes
[<a href="#Main">Main</a>] for a number of reasons:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>we are not limited to using classes derived from specific
abstract base classes (specialisation allows us to get round this
limitation)</p>
</li>
<li>
<p>we avoid the overhead of virtual function tables</p>
</li>
<li>
<p>we can even avoid using pointers altogether (if the
recompilation cost incurred is a relatively insignificant
factor);</p>
</li>
<li>
<p>we avoid the need for supporting class factories (typedefs are
sufficient).</p>
</li>
</ul>
</div>
<p>In conclusion, the lack of support for partial specialisation in
Visual C++ 6.0 is a serious inconvenience. However we should not
underestimate the power and usefulness of full specialisation which
it does support.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e250" id="d0e250"></a>References</h2>
</div>
<div class="bibliomixed"><a name="Alexandrescu" id=
"Alexandrescu"></a>
<p class="bibliomixed">[Alexandrescu] Andrei Alexandrescu, Modern
C++ Design, Addison Wesley C++ In Depth Series, 2001</p>
</div>
<div class="bibliomixed"><a name="Gamma-et-al" id=
"Gamma-et-al"></a>
<p class="bibliomixed">[Gamma-et-al] Erich Gamma, Richard Helm,
Ralph Johnson and John Vlissides, Design Patterns: Elements of
Reusable Object- Oriented Software, Addison Wesley, 1995</p>
</div>
<div class="bibliomixed"><a name="Goldthwaite" id=
"Goldthwaite"></a>
<p class="bibliomixed">[Goldthwaite] Lois Goldthwaite, &quot;Programming
With Interfaces In C++: A New Approach,&quot; Overload 40 (December
2000)</p>
</div>
<div class="bibliomixed"><a name="CVu14.1" id="CVu14.1"></a>
<p class="bibliomixed">[CVu14.1] &quot;Student Code Critique 14,&quot; C Vu
14.1 (February 2002)</p>
</div>
<div class="bibliomixed"><a name="Stroustrup" id="Stroustrup"></a>
<p class="bibliomixed">[Stroustrup] Bjarne Stroustrup, The C++
Programming Language, 3rd Edition, Addison Wesley, 1997</p>
</div>
<div class="bibliomixed"><a name="DIP" id="DIP"></a>
<p class="bibliomixed">[DIP] <span class="bibliomisc"><a href=
"http://www.objectmentor.com/resources/articles/dip.pdf" target=
"_top">http://www.objectmentor.com/resources/articles/dip.pdf</a></span></p>
</div>
<div class="bibliomixed"><a name="Main" id="Main"></a>
<p class="bibliomixed">[Main] Chris Main, &quot;OOD and Testing using
the Dependency Inversion Principle,&quot; C Vu 12.6 (December 2000)</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
