    <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 Fistful Of Idioms - Giving STL Iterators a Base
Class</title>
        <link>https://members.accu.org/index.php/journals/479</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 #38 - Jul 2000 + 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/c166/">38</a>
                    (6)
<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/c166-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c166+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 Fistful Of Idioms - Giving STL Iterators a Base
Class</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 26 July 2000 17:50:57 +01:00 or Wed, 26 July 2000 17:50:57 +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>Some little while ago, I posted a question on the <tt class=
"literal">accu-prog-questions</tt> list regarding virtual template
functions. The short answer I already knew - &quot;it cannot be done.&quot;
The slightly longer answer was provided by Kevlin Henney - &quot;it can
be done if you know how.&quot;</p>
<p>A template function cannot be made virtual because, as Kevlin
put it, &quot;The dynamic binding you want ... is more significant than
the polymorphism required to handle any type.&quot; The virtual function
table for the class would contain the address of the function
normally, but a template function may never be instantiated, or may
be instantiated multiple times. What is a poor compiler to do? Spit
it out with a diagnostic, probably (which is exactly what mine
did).</p>
<p>I thought that this could be overcome in a simple and idiomatic
manner. I was not far off the mark; the solution provided by Kevlin
is, in his words, a &quot;collaboration of idioms.&quot; I will try to
identify them as we go along.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e29" id="d0e29"></a>The Good, the
Bad and the Ugly</h2>
</div>
<p>Consider a class to write to a file. The format of a given file
is probably fixed (few files contain both fixed width and
comma-separated values), but a more general solution will provide
for several formats. Even better, a good solution will also provide
for extensions; today you may want only CSV and fixed width, but
tomorrow you may also require an ODBC data source. An obvious way
to do this is provide an interface class, with pure virtual
functions defining the interface to be implemented in derived
classes. Each derived class has knowledge of the layout and
delimiter requirements of the target.</p>
<pre class="programlisting">
class file_writer {
public:
  // pure virtual functions define the interface
};
class csv_writer : public file_writer {
  // implement virtual functions according to CSV format
};
class fixed_w_writer : public file_writer {
  // implement virtual functions according to fixed width format
};
</pre>
<p>The original requirement was for something along these lines. A
record writer function would take a range of values to be written
as a single record:</p>
<pre class="programlisting">
class file_writer {
public:
  // ...
  template&lt;class Iterator&gt;   virtual void write (Iterator begin, Iterator end) = 0;
};
</pre>
<p>As already mentioned, this can not be done directly. Three
possibilities immediately present themselves:</p>
<pre class="programlisting">
  virtual void write (std::vector&lt;std::string&gt;::const_iterator begin, 
                     std::vector&lt;std::string&gt;::const_iterator end);
  virtual void write (std::vector&lt;std::string&gt; container);
</pre>
<p>Neither of these is very pleasing; both tie you, as the client,
into a specific container and contained type. The first has
advantages over the second, in that you, the client, can pass only
a partial range if you wish. The <tt class="function">write()</tt>
function itself does not have to change. Both suffer from having to
specify the particular iterator to be used. For example, the
function would need to be overloaded for a reverse iterator.</p>
<p>The third option is to pass each value in the container in turn
to the <tt class="function">write()</tt> function. This has the
improvement over the previous solutions in that the container type
is no longer an issue, but has other limitations, a burden on the
client not least among them.</p>
<pre class="programlisting">
virtual void file_writer::write (const std::string &amp; value) = 0;
// ...
std::vector&lt;std::vector&lt;std::string&gt; &gt; values;
file_writer * csv_file = new csv_file_writer (file_name);
// ...
for (std::vector&lt;std::vector&lt;std::string&gt; &gt;::iterator record = values.begin();
    record != values.end(); ++record){
  std::vector&lt;std::string&gt;::iterator i = record-&gt;begin();
  while (i != record-&gt;end() {
    csv_file-&gt;write (*i);
    ++i;
    if (i != record-&gt;end()) {
      csv_file-&gt;write (&quot;,&quot;);
    }
  }
  csv_file-&gt;write (&quot;\n&quot;);
}
</pre>
<p>This code would probably do the job, but is prone to error,
slightly obfuscated (which could be helped with judicious use of
using declarations), and the client is required to know the format
of the output file - defeating the original object.</p>
<p>The clue to the solution is in the requirement. Ideally, we want
to be able to write</p>
<pre class="programlisting">
  virtual void write (any_iterator begin, any_iterator end);
</pre>
<p>So, a good starting point is a class called <tt class=
"classname">any_iterator</tt>.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e67" id="d0e67"></a>The Type With
No Name</h2>
</div>
<p>The reason for writing a function which operates on an iterator
range as a template function, is so that it will work with any
iterator (provided the function itself uses a conformant
interface). Given that fact, we need to be able to create an
<tt class="classname">any_iterator</tt> from, well, any iterator.
In this case, it is sufficient to be able to create one from any
<span class="bold"><b>Input Iterator</b></span>.</p>
<p>The concept of <span class="bold"><b>Input Iterator</b></span>
limits the scope of what we need to achieve in <tt class=
"classname">any_iterator</tt>. We need the following
operations:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>default construction</p>
</li>
<li>
<p>assignment/copy</p>
</li>
<li>
<p>equality compare</p>
</li>
<li>
<p>dereference</p>
</li>
<li>
<p>member access</p>
</li>
<li>
<p>pre increment</p>
</li>
<li>
<p>post increment</p>
</li>
<li>
<p>post increment and dereference</p>
</li>
</ul>
</div>
<p>On this basis, then, our <tt class="classname">any_iterator</tt>
class will provide the following member functions:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p><tt class="methodname">any_iterator()</tt></p>
</li>
<li>
<p><tt class="methodname">any_iterator (const any_iterator
&amp;)</tt></p>
</li>
<li>
<p><tt class="methodname">operator= (const any_iterator
&amp;)</tt></p>
</li>
<li>
<p><tt class="methodname">operator== (const any_iterator
&amp;)</tt></p>
</li>
<li>
<p><tt class="methodname">operator!= (const any_iterator
&amp;)</tt></p>
</li>
<li>
<p><tt class="methodname">operator*()</tt></p>
</li>
<li>
<p><tt class="methodname">operator-&gt;()</tt></p>
</li>
<li>
<p><tt class="methodname">operator++()</tt></p>
</li>
<li>
<p><tt class="methodname">operator++(int)</tt></p>
</li>
</ul>
</div>
<p>This provides our interface, but we have to decide, for example,
what <tt class="methodname">operator*()</tt> should return. We can
specialise the entire class on its contained type (in our original
requirement, <tt class="classname">std::string</tt>), or we can
parameterise the class on the contained type:</p>
<pre class="programlisting">
template&lt;typename Contained&gt; class any_iterator {
// ...
</pre>
<p>This latter method means that the signature for our <tt class=
"function">write()</tt> function becomes</p>
<pre class="programlisting">
  void write (any_iterator&lt;std::string&gt; begin, any_iterator&lt;std::string&gt; end)
</pre>
<p>which seems a reasonable compromise.</p>
<p>With this in mind, we can provide an implicit conversion from
any <span class="bold"><b>Input Iterator</b></span> (actually, from
anything, but the restrictions will come later) using a member
template function for a constructor.</p>
<pre class="programlisting">
template&lt;typename Iterator&gt;
any_iterator (const Iterator &amp; rhs);
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e179" id="d0e179"></a>Painting Your
Wagon</h2>
</div>
<p>The real magic of the solution is expressed in a Pattern called
&quot;External Polymorphism&quot; which is published as having the following
intent:</p>
<div class="blockquote">
<blockquote class="blockquote">
<p>Allow C++ classes unrelated by inheritance and/or having no
virtual methods to be treated polymorphically. These unrelated
classes can be treated in a common manner by software that uses
them. (Cleeland 1996)</p>
</blockquote>
</div>
<p>Standard Library Iterators are expressly not related by
inheritance; they are related by concept (Gamma+, 1995). They do
not have virtual functions, and cannot be treated polymorphically,
in the late-binding sense. Our requirements for <tt class=
"classname">any_iterator</tt> are to treat <span class=
"bold"><b>Iterators</b></span> as if they had a common ancestor.
They could then be treated in the common manner described
above.</p>
<pre class="programlisting">
  class interface   {
  public:
    // pure virtual interface declarations
  };
  template&lt;typename ConcreteType&gt; class adaptor : public interface {
  public:
// implementations of pure virtuals in base class
  private:
    ConcreteType adaptee;
  };
</pre>
<p>The <tt class="classname">adaptor</tt> class has member
functions which forward the call to the member function of
<tt class="methodname">ConcreteType</tt>. In this sense, this
structure is similar in some respects to the Adaptor pattern
(Gamma+, 1995), but it has differing motivations; it does not set
out to convert the interface of <tt class=
"methodname">ConcreteType</tt> in any way (athough it could), only
to provide <tt class="methodname">ConcreteType</tt> with
polymorphic behaviour. The client class, using a pointer to
interface, can use it as if it were a <tt class=
"methodname">ConcreteType</tt>.</p>
<p>In our <tt class="classname">any_iterator</tt> class, <tt class=
"methodname">ConcreteType</tt> is an iterator. We need to provide
in the interface those functions which will allow us to provide an
iterator-like interface in <tt class="classname">any_iterator</tt>.
A start is the following:</p>
<pre class="programlisting">
class wrapper {
public:
  virtual void next () = 0;
  virtual std::string &amp; current () const = 0;
  virtual bool equal (const wrapper * rhs) const = 0;
  virtual void assign (const wrapper * rhs) = 0;
};
template&lt;typename Iterator&gt; class adaptor : public wrapper {
public:
  adaptor (const Iterator &amp; rhs);
  virtual void next () 
    { ++adaptee; }
  virtual std::string &amp; current () const 
    { return *adaptee; }
  virtual bool equal (const wrapper * rhs) 
    { return adaptee == static_cast&lt;adaptor&lt;Iterator&gt; *&gt;(rhs)-&gt;adaptee; }
  virtual void assign (const wrapper * rhs)
    { adaptee = static_cast&lt;adaptor&lt;Iterator&gt; *&gt;(rhs)-&gt;adaptee; }
private:
  Iterator adaptee;
};
</pre>
<p>Note the addition of a conversion constructor in <tt class=
"classname">adaptor</tt>'s interface; that will become clear
shortly. There are a couple of gotcha's here. The first one to go
is the return from <tt class="methodname">current()</tt>. This is
the same contained type we already fixed in the <tt class=
"classname">any_iterator</tt> class by using a template parameter
to the class. The easiest way to parameterise this one is to nest
interface and <tt class="classname">adaptor&lt;&gt;</tt> inside
<tt class="classname">any_iterator</tt>.</p>
<pre class="programlisting">
template&lt;typename Contained&gt; class any_iterator {
public:
  // ...
private:
  class wrapper   {
  public:
    virtual void next () = 0;
    virtual Contained &amp; current () const = 0;
    virtual bool equal (const wrapper * rhs) const = 0;
    virtual void assign (const wrapper * rhs) const = 0;
  };
  template&lt;class Iterator&gt;   class adaptor : public wrapper {
    // ...
  };
};
</pre>
<p>The next problem is with <tt class="methodname">equal()</tt>.
The <i class="parameter"><tt>rhs</tt></i> pointer could have a
different adaptee type to <tt class="varname">this</tt> - in our
case, e.g., a <tt class="classname">list&lt;&gt;::iterator</tt>
when this one is a <tt class=
"classname">vector&lt;&gt;::iterator</tt>.</p>
<p>It is the polymorphic type which interests us, so we can make
use of RTTI to determine consistency of type:</p>
<pre class="programlisting">
  adaptor&lt;Iterator&gt; * tmp = dynamic_cast&lt;adaptor&lt;Iterator&gt;*&gt;(rhs);
  return tmp &amp;&amp; adaptee == tmp-&gt;adaptee;
</pre>
<p>The nature of using <tt class="literal">dynamic_cast</tt> on
pointers means that <tt class="varname">tmp</tt> will be <tt class=
"literal">null</tt> if the conversion fails, i.e. the runtime type
of <i class="parameter"><tt>rhs</tt></i> is different to this. To
make this fail more noisily, we could have <tt class=
"methodname">adaptor::equal()</tt> take a reference, and make
<tt class="varname">tmp</tt> a reference, thus forcing <tt class=
"literal">dynamic_cast</tt> to throw <tt class=
"exceptionname">std::bad_cast</tt> on failure.</p>
<p>Note that <tt class="methodname">assign()</tt> also suffers from
this problem, but we will address that one differently.</p>
<p>We now need access to this framework in the <tt class=
"classname">any_iterator</tt> class. The declarations are already
nested; all that remains is to define such a thing.</p>
<pre class="programlisting">
template&lt;typename Contained&gt; class any_iterator {
public:
// ...
private:
  class wrapper   {
// ...
  };  
  template&lt;typename Iterator&gt; class adaptor : public wrapper {
// ...
  };
  wrapper * body;
};
</pre>
<p>Now the member functions of <tt class=
"classname">any_iterator</tt> can operate on body which will
forward all requests to <tt class="classname">adaptee</tt>.</p>
<pre class="programlisting">
  const any_iterator&lt;Contained&gt; any_iterator&lt;Contained&gt;::operator++ (int) {
    body-&gt;next();
    return *this;
  }
  bool any_iterator&lt;Contained&gt;::operator== (const any_iterator &amp; rhs) {
    return body-&gt;equal (rhs.body);
  }
  // ...
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e315" id="d0e315"></a>A Few Idioms
More...</h2>
</div>
<p>So far, so good. However, the functions we have created only
work if we have an actual instance of body. Recall the converting
constructor being a member template function. The template type of
the <tt class="classname">Iterator</tt> is known at this point, and
we can construct a new <tt class="classname">adaptor</tt> object
accordingly:</p>
<pre class="programlisting">
template&lt;typename Contained&gt;
template&lt;typename Iterator&gt;
any_iterator&lt;Contained&gt;::any_iterator (const Iterator &amp; rhs)
  : body (new adaptor&lt;Iterator&gt;(rhs)) { }
</pre>
<p>The copy constructor is more of a problem; we have no way of
identifying the Iterator type for <tt class=
"varname">rhs-&gt;body</tt></p>
<pre class="programlisting">
  any_iterator&lt;Contained&gt;::any_iterator (const any_iterator&lt;Contained&gt; &amp; rhs) {
    // ???
  }
</pre>
<p>nd so have no way of creating a new instance of it. This
identifies a need for a new idiom in the <tt class=
"classname">adaptor</tt> class: a Virtual Copy Constructor (Henney,
1999, Cline, 1991, Koenig, 1997).</p>
<p>A constructor for a class cannot be virtual. Normally, you know
the concrete type of the object being created, and so this does not
cause a problem. In some circumstances (here for example), we have
only access to the base class type of the object we want to
construct. It is meaningless to create an empty one, but perfectly
reasonable to require a copy, or a clone. It forms part of the
interface to the <tt class="classname">wrapper</tt> class</p>
<pre class="programlisting">
  wrapper * wrapper::clone () const = 0;
</pre>
<p>and is implemented in <tt class="classname">adaptor</tt>:</p>
<pre class="programlisting">
  template&lt;typename Iterator&gt;
  wrapper * adaptor&lt;Iterator&gt;::clone () const {
    return new adaptor&lt;Iterator&gt;(adaptee);
  }
</pre>
<p>This uses the already given conversion from <tt class=
"classname">Iterator</tt> (the type of <tt class=
"classname">adaptee</tt>), which has been used before in the
conversion constructor of <tt class="classname">any_iterator</tt>.
The return from <tt class="methodname">clone()</tt> could be
covariant, i.e. return a pointer to the actual class rather than a
pointer to its base class, but there is no benefit in this, since
the target for the returned pointer is a pointer to the base class;
it will not be used as part of an expression such as</p>
<pre class="programlisting">
  Contained string_value = body-&gt;clone()-&gt;current();
</pre>
<p>(Aside to users of Borland C++Builder 4/5 - I originally
declared a copy constructor for <tt class="classname">adaptor</tt>
thus:</p>
<pre class="programlisting">
  adaptor (const adaptor&lt;Iterator&gt; &amp; rhs);
</pre>
<p>but the entire class refused to compile. Removing the template
type from the <i class="parameter"><tt>rhs</tt></i> parameter
solved the problem legally, a language construct I had not
previously encountered - but the diagnostics were not helpful in
reaching this conclusion!)</p>
<p>This allows us to write a copy constructor for <tt class=
"classname">any_iterator</tt> as</p>
<pre class="programlisting">
template&lt;typename Contained&gt;
any_iterator&lt;Contained&gt;::any_iterator (const any_iterator &amp; rhs)
  : body (rhs.body ? rhs.body-&gt;clone () : 0) { }
</pre>
<p>Having defined a copy constructor, we now need a copy assignment
operator, which brings us to another idiom - Copy Before Release
(CBR). Self assignment is not a problem in a class with only
intrinsic data types (or those that provide the same copy semantics
of intrinsics); but then, if only intrinsic data types are present,
we can do without copy construction and copy assignment altogether,
leaving the compiler to provide the necessary logic.</p>
<p>This actually leaves us at the Rule of Three - if you need any
one of copy constructor, copy assignment operator, destructor, you
generally need all three. (Cline, 1991, Coplien, 1992).</p>
<p>Since the data member of <tt class="classname">any_iterator</tt>
is a pointer, we require a proper deep copy to be performed on
assignment. We also need to ensure that assignment to self does not
occur. Finally, assignment should be exception safe, meaning it
will operate correctly in the presence of an exception.</p>
<p>The idiom which expresses all these things is Copy Before
Release (Henney, 1998). At its most basic level, using the current
example, it is implemented as</p>
<pre class="programlisting">
any_iterator&lt;Contained&gt; &amp; any_iterator&lt;Contained&gt;::operator= (
                            const any_iterator&lt;Contained&gt; &amp; rhs){
  wrapper * tmp = body-&gt;clone();
  delete body;
  body = tmp.body;
  return *this;
}
</pre>
<p>As you can see, the name given this idiom is apt. It turns out
that this can be simplified using a suitable copy constructor. We
have already defined the copy constructor for <tt class=
"classname">any_iterator</tt>, and so can use that. Further more,
exception safety can be guaranteed by using <tt class=
"function">std::swap()</tt>.This leads to a remarkably simple
implementation (Sutter,1999):</p>
<pre class="programlisting">
any_iterator&lt;Contained&gt; &amp; any_iterator&lt;Contained&gt;::swap(any_iterator&lt;Contained&gt; &amp; rhs){
  std::swap (body, rhs.body);
  return *this;
}
any_iterator&lt;Contained&gt; &amp; any_iterator&lt;Contained&gt;::operator= (
                            const any_iterator&lt;Contained&gt; &amp; rhs){
  swap (any_iterator&lt;Contained&gt; (rhs));  
  return *this;
}
</pre>
<p>The <tt class="methodname">swap()</tt> member function merely
swapping two pointers may look a little suspect, but the call to it
provides the insight. We create a new copy of the <i class=
"parameter"><tt>rhs</tt></i> and swap it with this. When the call
to <tt class="methodname">swap()</tt> completes, the temporary
object constructed in its arguments goes out of scope, taking its
pointer with it. At that point, its body pointer is the memory
which used to be attached to <tt class="varname">this</tt>, whereas
<tt class="varname">this-&gt;body</tt> points at newly allocated
memory containing a copy of <i class=
"parameter"><tt>rhs</tt></i>.</p>
<p>This safely handles null assignment, self assignment and
exceptions (such as <span class="errortype">std::bad_alloc</span>),
as well as a successful copy. If an exception does occur, via the
<tt class="classname">any_iterator</tt> copy constructor, then this
will remain in its previous state, because the copy will not
occur.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e439" id=
"d0e439"></a>Conclusion</h2>
</div>
<p>The whole premise of this technique revolves around being able
to silently convert from a STL iterator to an <tt class=
"classname">any_iterator</tt>. In the wider sense (see Cleeland,
1996), it can be used to superimpose polymorphic behaviour on other
concrete types. This property of encouraging silent conversions is,
rightly, regarded as dangerous (when C++ is described as a language
which enables you to shoot yourself in the foot, this is one of the
big shooters), but under specific conditions, such as those
described here, it may be inescapable.</p>
<p>The circumstances under which it is considered dangerous are
generally where the converted type appears as a parameter to a
function; however, this is exactly the circumstance under which
this idiom is intended to be used. Here is an example.</p>
<pre class="programlisting">
  void csv_writer::write (const any_iterator&lt;std::string&gt; &amp;begin,
                          const any_iterator&lt;std::string&gt; &amp; end) { /* ...*/ }
  // ...
  csv_writer cw;
  std::vector&lt;std::string&gt; records;
  // initialisation of vector with strings here

  // using ordinary STL iterators from vector. It's also perfectly
  // valid to use reverse_iterators or const_iterators
  cw.write (records.begin(), records.end());
  // similarly, we can use istream_iterators because the basis for 
  // any_iterator is the Input Iterator, which is modelled by 
  // istream_iterator
  std::ifstream  strm (file_name);  
  cw.write (std::istream_iterator&lt;std::string&gt;(strm), 
            std::istream_iterator&lt;std::string&gt; ());
</pre>
<p>This extract demonstrates the use of <tt class=
"classname">any_iterator</tt>. The intention is that client code
never uses - indeed, probably does not even need to know about -
the <tt class="classname">any_iterator</tt> type directly, but is
able to use it transparently because it exhibits properties to
allow this.</p>
<p>See bottom of next page for acknowledgements and bibliography
(<i><span class="remark">sorry, but I seem to have mislaid
themduring the process of preparing this for publication
FG</span></i>)</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
