[Debtags-devel] Hello, and a few improved tag descriptions

Benjamin Mesing bensmail@gmx.net
Fri, 03 Jun 2005 13:51:25 +0200


--=-GvwyjtNOARVzHhioIuI8
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hello,



> I liked the idea of a tighter integration between Debtags classes and
> the STL, like making Debtags classes work with STL algorithms; and I
> heard something nice about adaptor classes, that turn an operator()
> invocation in a consumer::consume() invocation or an invocation of any
> other method of a class which is not specifically a consumer.
> 
> That would mean that a class wouldn't need to be a consumer to get
> packages, and that many of its methods could be fed packages by some
> producer.
I am fan of C++ and I also appreciate the possibility to use functors.
But in my opinion functors are most usefull when providing algorithms.
Implementing an interface is far more expressive than overloading the
operator(). Others might disagree here... 
Functors do make sense from time to time (consider the for_each
function). But also note, that the C++ way of using templates for
algorithms in combination with adapters and binders are complicated to
use, mostly less readable than explicit loops and not as flexible as one
might expect. I worked hard to achieve my goals using std algorithms
because Stroustrup is so fond of them, but finally I gave up because of
the problems mentioned above. Nevertheless there might be one or another
std::for_each or std::copy flying around in packagesearch.
That said, I summarize myy opinion in going with Mike: Be carefull with
functors.


I've attached an article discussing the limitations of adapters and
binders.

Greetings Ben




--=-GvwyjtNOARVzHhioIuI8
Content-Disposition: attachment; filename=adapter_binder.html
Content-Type: text/html; name=adapter_binder.html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<!--Converted with LaTeX2HTML 99.2beta6 (1.42)
original version by:  Nikos Drakos, CBLU, University of Leeds
* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>Adapters and Binders - Overcoming problems
in the design and implementation of the C++-STL</TITLE>
<META NAME="description" CONTENT="Adapters and Binders - Overcoming problems
in the design and implementation of the C++-STL">
<META NAME="keywords" CONTENT="adapter_binder">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="LaTeX2HTML v99.2beta6">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">

<LINK REL="STYLESHEET" HREF="adapter_binder.css">

</HEAD>

<BODY >

<P>

<P>

<P>

<H1 ALIGN="CENTER">Adapters and Binders - Overcoming problems
<BR>in the design and 
       implementation of the C++-STL</H1>
<P ALIGN="CENTER"><STRONG>Volker Simonis<A NAME="tex2html1"
  HREF="#foot477"><SUP><SPAN CLASS="arabic">1</SPAN></SUP></A>
<BR>  Universit&#228;t T&#252;bingen
</STRONG></P>
<P ALIGN="CENTER"><STRONG>February 28, 2000</STRONG></P>

<P>

<H3>Abstract:</H3>
<DIV CLASS="ABSTRACT">
  
  The Standard Template Library [<A
 HREF="adapter_binder.html#Lee-Step">Lee-Step</A>], 
  [<A
 HREF="adapter_binder.html#SGI-STL">SGI-STL</A>], had the reputation of being complex and hard to
  use. Because of its exhaustive use of the new 
  C++ language features, most compilers weren't able to fully support
  this library. Nowadays, new compilers and the standardisation of 
  C++ [<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>] not only enable us to use the STL in its
  full strength, but also show us the drawbacks of a library which 
  apparently was designed from scratch without the possibility of testing and 
  using it. 
  This paper will focus on the syntax and semantics of
  STL Adaptors and Binders. It will reveal some shortcomings in their C++
  implementation and suggest  solutions for the encountered problems.

<P>

  <B>Keywords:</B>  C++, STL, adapters, binders, template specialisation
</DIV>
<P>

<P>

<P>

<H1><A NAME="SECTION00010000000000000000">
<SPAN CLASS="arabic">1</SPAN> Introduction</A>
</H1>

<P>
The STL is a new kind of library for many C++ users. Rather than being
another class hierarchy of derived classes like so many other libraries which 
exploit mainly the object oriented features of the language, the STL sets its 
main focus on genericity. As a consequence, the main elements of the library,
namely containers and algorithms, are coupled together by iterators. There are
no sub-class relationships between the components. They can only work
together by implementing a common interface. This is the characteristic of 
generic programming. Algorithms are designed for a special domain for which a 
set of requirements have to hold. Once the algorithms are implemented, they can
be used with arbitrary input domains, as long as they fulfill the requirements.

<P>
The opportunity of implementing such kinds of generic libraries in C++ was
a result of the introduction of template mechanisms into the language.
Unfortunately, the intensive use of templates pushes even the newest 
C++-compilers to their limits. Especially error messages, which are 
inevitable
during every development process, appear to be unreadable even to experienced
C++ programmers, if they occur in multiply nested template instantiations.
This may be one reason, why few big projects in the software industry are
build on top of the STL until now. Another reason can be the fact that this 
library didn't really grew together with the language and the requirements
of its users. Instead it was designed ``from scratch'', even before the 
language was ready to compile it<A NAME="tex2html2"
  HREF="#foot1315"><SUP><SPAN CLASS="arabic">2</SPAN></SUP></A>.

<P>

<H1><A NAME="SECTION00020000000000000000"></A>
<A NAME="Adapters"></A><BR>
<SPAN CLASS="arabic">2</SPAN> Adapters
</H1>

<P>
In the STL, adapters are used to build function objects out of ordinary
functions or class methods. In fact, most of the predefined
STL algorithms don't care about their argument being a function or a function
object. However some standard algorithms, like for example <TT>bind()</TT> 
which we will discuss in more detail in the next section, rely on the fact
that their argument is a function object. In this case a ``pointer to function
adapter'' can be used to transform a function pointer into an function object.

<P>
Since algorithms invoke their function argument by simply calling the arguments
function operator, it would not be possible for algorithms to call a member 
function for all their operands. In this case, a member function adapter can be
used which transforms a member function into a general function object. Let's 
have a look at an example adapted from [<A
 HREF="adapter_binder.html#Strou97">Strou97</A>](18.4.4.2):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">void</SPAN> draw_all(list&#60;Shape&#62; &#38;ls) {
  for_each(ls.begin(), ls.end(), mem_fun_ref(&#38;Shape::draw));
}
</PRE>
<TR>
</TABLE>
<BR>

Provided that <TT>Shape</TT> is a class which provides a <TT>draw</TT> method,
the function <TT>draw_all</TT> will call <TT>draw</TT> for every 
<TT>Shape</TT> object inside its <TT>list</TT> argument. The adapter
<TT>mem_fun_ref</TT> which is defined in <TT>&lt;functional&gt;</TT> as 
follows [<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#7):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T&#62;
mem_fun_ref_t&#60;R, T&#62; mem_fun_ref(R (T::*pm)());
</PRE>
<TR>
</TABLE>
<BR>

transforms its argument, a pointer to a member function without arguments,
into a function object of type <TT>mem_fun_ref_t</TT>. Note however that
<TT>mem_fun_ref_t</TT> is a unary function and its function operator takes
one argument, namely the object for which the method will be called. The 
definition of <TT>mem_fun_ref_t</TT> is [<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#5):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T&#62;
<SPAN STYLE="color : maroon; ">struct</SPAN> mem_fun_ref_t : <SPAN STYLE="color : maroon; ">public</SPAN> unary_function&#60;T, R&#62; {
  <SPAN STYLE="color : maroon; ">explicit</SPAN> mem_fun_ref_t(R (T::*pm)());
  R <SPAN STYLE="color : maroon; ">operator</SPAN>() (T &#38;x) <SPAN STYLE="color : maroon; ">const</SPAN>;
};
</PRE>
<TR>
</TABLE>
<BR>

Because the called method will not be <TT>const</TT> in general, the object
argument of the function operator cannot be <TT>const</TT> too. For 
<TT>const</TT> methods, an overloaded version of <TT>mem_fun_ref</TT> 
([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#13)) is
available, which returns a function object of type
<TT>const_mem_fun_ref_t</TT> ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#11)).

<P>
<A NAME="constMemRef"></A>
<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T&#62;
<SPAN STYLE="color : maroon; ">struct</SPAN> const_mem_fun_ref_t : <SPAN STYLE="color : maroon; ">public</SPAN> unary_function&#60;T, R&#62; {
  <SPAN STYLE="color : maroon; ">explicit</SPAN> mem_fun_ref_t(R (T::*pm)() <SPAN STYLE="color : maroon; ">const</SPAN>);
  R <SPAN STYLE="color : maroon; ">operator</SPAN>() (<SPAN STYLE="color : maroon; ">const</SPAN> T &#38;x) <SPAN STYLE="color : maroon; ">const</SPAN>;
};
<SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T&#62;
const_mem_fun_ref_t&#60;R, T&#62; mem_fun_ref(R (T::*pm)() <SPAN STYLE="color : maroon; ">const</SPAN>);
</PRE>
<TR>
</TABLE>
<BR>

In this case, the argument of the function operator can be constant, as it is
common sense and good programming style in C++.
All this details seem to be not very important, but they will turn out be 
crucial if adapters are to be combined with binders as we will see in the next
section.

<P>
For now lets have a look at the remaining overloaded versions of the
<TT>mem_fun_ref</TT> function. They take a pointer to a member function with
one argument or a pointer to a constant member function with one
argument respectively and return binary function 
objects ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#7,20.3.8#13)). 

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T, <SPAN STYLE="color : maroon; ">class</SPAN> A&#62;
mem_fun1_ref_t&#60;R, T, A&#62; mem_fun_ref(R (T::*pm)(A));
<SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T, <SPAN STYLE="color : maroon; ">class</SPAN> A&#62;
const_mem_fun1_ref_t&#60;R, T, A&#62; mem_fun_ref(R (T::*pm)(A) <SPAN STYLE="color : maroon; ">const</SPAN>);
</PRE>
<TR>
</TABLE>
<BR>

As in the previous
case notice the fact that unary functions are transformed into binary function
objects which await as additional argument the object for which 
the method will be invoked. Only the non-const version of 
<TT>mem_fun1_ref_t</TT> will be shown here ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.8#6)):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN>&#60;<SPAN STYLE="color : maroon; ">class</SPAN> R, <SPAN STYLE="color : maroon; ">class</SPAN> T, <SPAN STYLE="color : maroon; ">class</SPAN> A&#62;
<SPAN STYLE="color : maroon; ">struct</SPAN> mem_fun1_ref_t : <SPAN STYLE="color : maroon; ">public</SPAN> binary_function&#60;T, A, R&#62; {
  <SPAN STYLE="color : maroon; ">explicit</SPAN> mem_fun_ref_t(R (T::*pm)(A));
  R <SPAN STYLE="color : maroon; ">operator</SPAN>() (T &#38;x, A arg) <SPAN STYLE="color : maroon; ">const</SPAN>;
};
</PRE>
<TR>
</TABLE>
<BR>

An additional difficulty with the member function adapters is the unintuitive
pointer to member syntax. If the class <TT>Shape</TT> from the above example
would define a second <TT>draw</TT> method which takes an <TT>int</TT>
argument, we could not write

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;">for_each(ls.begin(), ls.end(), mem_fun_ref(&#38;Shape::draw));
</PRE>
<TR>
</TABLE>
<BR>

anymore. Instead we had to explicitly qualify the method name with the
desired type:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;">for_each(ls.begin(), ls.end(), mem_fun_ref((<SPAN STYLE="color : maroon; ">void</SPAN> (Shape::*)(<SPAN STYLE="color : maroon; ">void</SPAN>))&#38;Shape::draw));
</PRE>
<TR>
</TABLE>
<BR>

In this case a <TT>typedef</TT> could be a good alternative to simplify
the expression. 

<P>
Of course operators also can be used as arguments for member
function adapters. Consider the following example:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">struct</SPAN> Int {
  <SPAN STYLE="color : maroon; ">int</SPAN> _i;
  Int(<SPAN STYLE="color : maroon; ">int</SPAN> i) : _i(i) {}
  Int&#38; <SPAN STYLE="color : maroon; ">operator</SPAN>++ ()    { ++_i; <SPAN STYLE="color : maroon; ">return</SPAN> *<SPAN STYLE="color : maroon; ">this</SPAN>; }            <SPAN STYLE="color : red; ">// prefix  increment</SPAN>
  Int  <SPAN STYLE="color : maroon; ">operator</SPAN>++ (<SPAN STYLE="color : maroon; ">int</SPAN>) { Int i(*<SPAN STYLE="color : maroon; ">this</SPAN>); ++_i; <SPAN STYLE="color : maroon; ">return</SPAN> i; }  <SPAN STYLE="color : red; ">// postfix increment</SPAN>
};
<SPAN STYLE="color : maroon; ">void</SPAN> increment_all(vector&#60;Int&#62; &#38;vi) {
  for_each(vi.begin(), vi.end(), mem_fun_ref((Int (Int::*)())&#38;Int::<SPAN STYLE="color : maroon; ">operator</SPAN>++));
}
</PRE>
<TR>
</TABLE>
<BR>

It uses the prefix increment oprator. But what if we absolutely want to use 
the postfix operator (though it is no difference in this context of course)? 
Let's try:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">void</SPAN> increment_all_(vector&#60;Int&#62; &#38;vi) {
  for_each(vi.begin(), vi.end(), mem_fun_ref((Int (Int::*)(<SPAN STYLE="color : maroon; ">int</SPAN>))&#38;Int::<SPAN STYLE="color : maroon; ">operator</SPAN>++));
}
</PRE>
<TR>
</TABLE>
<BR>

A compiler error will occur, reporting something like: ``No match for call to
<TT>(mem_fun1_ref_t&lt;Int, Int,int&gt;) (Int&amp;)</TT>''. Not quit what we expected 
but rather one of the confusing error messages mentioned above. What does it 
mean? We clearly adviced the compiler to take the postfix increment operator 
and this operator is a unary function, no matter if it's argument is used or 
not. We could even apply a default argument, it would be no difference, since 
it would not change the signature of the method.
Consequently the <TT>mem_fun_ref</TT> version for unary methods is called
which creates a binary function object of type <TT>mem_fun1_ref_t</TT>.
The function operator of this object of course is binary too with a signature 
of type <TT>Int (::*)(Int&amp;, int)</TT>. Therefor the call to a binary function
demanded by the <TT>for_each()</TT> function cannot be resolved, resulting
in the mentioned compiler error.

<P>
So in fact, after rethinking the situation we must admit that the compiler is
not wrong, nor is this a problem of the STL. Rather this is a C++ problem
because C++ allows us to hide the real signature and thus the type of 
functions. This can be done either by
supplying them with default arguments or by convention, like this is the case 
with the postfix increment operator.
A library based on algebraic rules like the STL, merciless unhides such 
inaccuracies in the language definition.
But the situation is not hopeless. After having understood the problem we can
fix it with the help of another construct from the STL - namely binders.

<P>

<H1><A NAME="SECTION00030000000000000000"></A>
<A NAME="Binders"></A><BR>
<SPAN CLASS="arabic">3</SPAN> Binders
</H1>

<P>
Binders can be used to bind one argument of a binary function object to a fixed
value thus transforming it into an unary function. Therewith we could write 
the broken version of <TT>increment_all</TT> in the following way:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">void</SPAN> increment_all(vector&#60;Int&#62; &#38;vi) {
  for_each(vi.begin(), vi.end(), bind2nd(mem_fun_ref((Int (Int::*)(<SPAN STYLE="color : maroon; ">int</SPAN>))&#38;Int::<SPAN STYLE="color : maroon; ">operator</SPAN>++), 999));
}
</PRE>
<TR>
</TABLE>
<BR>

By binding the integer argument of <TT>mem_fun1_ref_t</TT>'s function
operator (its 2nd argument) to 999, we get a unary function object, 
exactly as expected
by <TT>for_each()</TT>. Notice that in this case it is unimportant to which
value the argument is bound, since the call to <TT>mem_fun1_ref_t</TT>'s
function operator will be resolved into a call to <TT>Int</TT>'s postfix
increment operator which ignores its argument anyway.

<P>
This looks quit satisfying, unfortunately it will depend solely on your 
compiler if this will compile and run. In any case, according to the C++ 
standard it should definitely not. To understand why, we must take a closer 
look on <TT>bind2nd()</TT>'s implementation ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.6.4)):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> Operation, <SPAN STYLE="color : maroon; ">class</SPAN> Arg2&#62;
<SPAN STYLE="color : maroon; ">inline</SPAN> binder2nd&#60;Operation&#62; bind2nd(<SPAN STYLE="color : maroon; ">const</SPAN> Operation&#38; op, <SPAN STYLE="color : maroon; ">const</SPAN> Arg2&#38; x) {
  <SPAN STYLE="color : maroon; ">return</SPAN> binder2nd&#60;Operation&#62;(op, <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::second_argument_type(x));
}
</PRE>
<TR>
</TABLE>
<BR>

<TT>bind2nd()</TT> expects it's argument to be a binary function object derived 
from <TT>binary_function</TT> which is declared as well as 
<TT>unary_function</TT> in the standard header <TT>&lt;functional&gt;</TT>. These
structs only define the types of their arguments and their result type for 
later use. For your convenience, here the definition of 
<TT>binary_function</TT> ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.1)):

<P>
<A NAME="binaryFunction"></A>
<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> Arg1, <SPAN STYLE="color : maroon; ">class</SPAN> Arg2, <SPAN STYLE="color : maroon; ">class</SPAN> Result&#62;
<SPAN STYLE="color : maroon; ">struct</SPAN> binary_function {
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Arg1 first_argument_type;
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Arg2 second_argument_type;
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Result result_type;
};      
</PRE>
<TR>
</TABLE>
<BR>

Notice how <TT>bind2nd()</TT> uses this type information to cast the argument of
type <TT>Arg2</TT> into the type of the function objects second argument. This
is crucial in order to call the constructor of <TT>binder2nd</TT> if the types
don't match exactly and there's no standard conversion available.

<P>
As you would expect, <TT>binder2nd</TT>, the result returned by the call to
<TT>bind2nd()</TT>, is a unary function object derived from 
<TT>unary_function</TT>. It has the following definition
([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](20.3.6.3)):

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> Operation&#62; 
<SPAN STYLE="color : maroon; ">class</SPAN> binder2nd : <SPAN STYLE="color : maroon; ">public</SPAN> unary_function&#60;<SPAN STYLE="color : maroon; ">typename</SPAN> Operation::first_argument_type,
                                        <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::result_type&#62; {
<SPAN STYLE="color : maroon; ">protected</SPAN>:
  Operation op;
  <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::second_argument_type value;
<SPAN STYLE="color : maroon; ">public</SPAN>:
  binder2nd(<SPAN STYLE="color : maroon; ">const</SPAN> Operation&#38; x, <SPAN STYLE="color : maroon; ">const</SPAN> <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::second_argument_type&#38; y) 
      : op(x), value(y) {}
  <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::result_type
  <SPAN STYLE="color : maroon; ">operator</SPAN>()(<SPAN STYLE="color : maroon; ">const</SPAN> <SPAN STYLE="color : maroon; ">typename</SPAN> Operation::first_argument_type&#38; x) <SPAN STYLE="color : maroon; ">const</SPAN> { <SPAN STYLE="color : maroon; ">return</SPAN> op(x, value); }
};
</PRE>
<TR>
</TABLE>
<BR>
It stores the binary function object and the second argument. The function
operator is defined in such a way that it takes only one argument. It then
calls the function operator of the stored function object with its argument
and the stored second argument which is fixed for the life time of the
<TT>binder2nd</TT> object.

<P>
The problem that arises now consists in the fact that the function operator of
<TT>binder2nd</TT> declares its argument with a <TT>const</TT> modifier, thus 
assuring not to alter its value. This is not unusual and considered to be
good programming style in C++. But it is fatal in the case where
<TT>bind2nd()</TT> is applied to the result of <TT>mem_fun_ref()</TT>, because
<TT>mem_fun_ref()</TT> creates a binary function of which the first 
argument is an object for which a certain method has to be called. Of
course it is impossible to assume constness for this object unless the method
which will be called is declared to be constant. In general, this will not 
hold. On the contrary, for this case the STL defines two special structs
<TT>const_mem_fun_ref_t</TT> and <TT>const_mem_fun1_ref_t</TT>. The only 
difference between them and the corresponding non-const structs
<TT>mem_fun_ref_t</TT> and <TT>mem_fun1_ref_t</TT> is the fact that the 
argument taken by the function operator is declared to be <TT>const</TT> in the 
former ones (see section <A HREF="adapter_binder.html#Adapters">2</A>, on page <A HREF="adapter_binder.html#constMemRef"><IMG  ALIGN="BOTTOM" BORDER="1" ALT="[*]"
 SRC="file:/share/software/latex2html99b6/icons/crossref.gif"></A>).

<P>
But in the general case, <TT>binder2nd</TT> will store a 
<TT>mem_fun1_ref_t</TT> as its operation parameter and it will try to call
<TT>mem_fun1_ref_t</TT>'s function operator with a <TT>const</TT> modified
object as first argument. This call will result in compiler error because it
discards the constness of the object passed as the first argument to 
<TT>mem_fun1_ref_t</TT>'s function operator. 

<P>
No general solution can be given for this problem. One possibility would be
to relax the postconditions of <TT>binder2nd</TT>'s function operator by
removing the <TT>const</TT> modifier from its function argument. This would
work fine for our example but it results in a STL not compatible with the
standard anymore. Even worse, it could break existing code which relies
on the argument of <TT>binder2nd</TT>'s function operator to be constant.

<P>
So the only viable way is the specialization of <TT>binder2nd</TT> for a
template argument of type <TT>mem_fun1_ref_t</TT>. Notice that this 
explicit specialization has to be declared before it's first use 
([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](14.7.3)). The specialization will look as follows:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> A, <SPAN STYLE="color : maroon; ">class</SPAN> B, <SPAN STYLE="color : maroon; ">class</SPAN> C&#62; 
<SPAN STYLE="color : maroon; ">class</SPAN> binder2nd&#60;mem_fun1_ref_t&#60;A,B,C&#62; &#62; 
  : <SPAN STYLE="color : maroon; ">public</SPAN> unary_function&#60;<SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::first_argument_type,
                          <SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::result_type&#62; {
<SPAN STYLE="color : maroon; ">protected</SPAN>:
  mem_fun1_ref_t&#60;A,B,C&#62; op;
  <SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::second_argument_type value;
<SPAN STYLE="color : maroon; ">public</SPAN>:
  binder2nd(<SPAN STYLE="color : maroon; ">const</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;&#38; x,
            <SPAN STYLE="color : maroon; ">const</SPAN> <SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::second_argument_type&#38; y) 
      : op(x), value(y) {}
  <SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::result_type
  <SPAN STYLE="color : maroon; ">operator</SPAN>()(<SPAN STYLE="color : maroon; ">typename</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;::first_argument_type&#38; x) <SPAN STYLE="color : maroon; ">const</SPAN> {
    <SPAN STYLE="color : maroon; ">return</SPAN> op(x, value); 
  }
};
</PRE>
<TR>
</TABLE>
<BR>

The only difference with respect to the general version is the missing 
<TT>const</TT> modifier for the function operators argument.
With the declaration of <TT>mem_fun1_ref_t</TT> in mind, this can slightly
be simplified into:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> A, <SPAN STYLE="color : maroon; ">class</SPAN> B, <SPAN STYLE="color : maroon; ">class</SPAN> C&#62; 
<SPAN STYLE="color : maroon; ">class</SPAN> binder2nd&#60;mem_fun1_ref_t&#60;A,B,C&#62; &#62; : <SPAN STYLE="color : maroon; ">public</SPAN> unary_function&#60;B,A&#62; {
<SPAN STYLE="color : maroon; ">protected</SPAN>:
  mem_fun1_ref_t&#60;A,B,C&#62; op;
  C value;
<SPAN STYLE="color : maroon; ">public</SPAN>:
  binder2nd(<SPAN STYLE="color : maroon; ">const</SPAN> mem_fun1_ref_t&#60;A,B,C&#62;&#38; x, <SPAN STYLE="color : maroon; ">const</SPAN> C&#38; y) : op(x), value(y) {}
  A <SPAN STYLE="color : maroon; ">operator</SPAN>()(B&#38; x) <SPAN STYLE="color : maroon; ">const</SPAN> {
    <SPAN STYLE="color : maroon; ">return</SPAN> op(x, value); 
  }
};
</PRE>
<TR>
</TABLE>
<BR>

With this explicitly specialized version of <TT>binder2nd</TT> our example
from the previous section will compile and run without errors. Hopefully, it
will be incorporated into a future version of the STL. It is also interesting 
to mention Stroustrups book ([<A
 HREF="adapter_binder.html#Strou97">Strou97</A>]) here. In section 18.4.4, in which
he introduces binders, adapters and negators, he presents the following 
example:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">void</SPAN> rotate_all(list&#60;Shape*&#62;&#38; ls, <SPAN STYLE="color : maroon; ">int</SPAN> angle) {
  for_each(ls.begin(), ls.end(), bind2nd(mem_fun(&#38;Shape::rotate), angle));
}
</PRE>
<TR>
</TABLE>
<BR>

If we assume <TT>rotate</TT> to be a non-const method of <TT>Shape</TT> as 
defined in section 2.6 of his book, this example will not work as well,
because of the reasons mentioned above. Notice that the only difference between
<TT>mem_fun()</TT> and <TT>mem_fun_ref()</TT> is that <TT>mem_fun()</TT>
creates a function object which expects an object pointer as argument
whereas the function object created by <TT>mem_fun_ref()</TT> expects a 
reference to an object. To fix the problem in Stroustrups book,
<TT>binder2nd</TT> has to be 
specialized for <TT>mem_fun1_t</TT> in the same way it was specialized for 
<TT>mem_fun1_ref_t</TT> whereby <TT>mem_fun1_t</TT> is the type of the 
object returned by <TT>mem_fun()</TT>.

<P>

<H2><A NAME="SECTION00031000000000000000">
<SPAN CLASS="arabic">3</SPAN>.<SPAN CLASS="arabic">1</SPAN> Binders and references</A>
</H2>

<P>
Now that the problems which arose through the interaction of adapters and
binders seemed to be solved, let's somewhat extend the example from section
<A HREF="adapter_binder.html#Adapters">2</A>. We refine the class <TT>Int</TT> as follows:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">struct</SPAN> Int {
  <SPAN STYLE="color : maroon; ">int</SPAN> _i;
  Int(<SPAN STYLE="color : maroon; ">int</SPAN> i) : _i(i) {}
  Int&#38; <SPAN STYLE="color : maroon; ">operator</SPAN>++ ()    { ++_i; <SPAN STYLE="color : maroon; ">return</SPAN> *<SPAN STYLE="color : maroon; ">this</SPAN>; }            <SPAN STYLE="color : red; ">// prefix  increment</SPAN>
  Int  <SPAN STYLE="color : maroon; ">operator</SPAN>++ (<SPAN STYLE="color : maroon; ">int</SPAN>) { Int i(*<SPAN STYLE="color : maroon; ">this</SPAN>); ++_i; <SPAN STYLE="color : maroon; ">return</SPAN> i; }  <SPAN STYLE="color : red; ">// postfix increment</SPAN>
  Int&#38; add(Int i)       { _i+= i._i; <SPAN STYLE="color : maroon; ">return</SPAN> *<SPAN STYLE="color : maroon; ">this</SPAN>; }
};
</PRE>
<TR>
</TABLE>
<BR>

with the only change being the additional method <TT>add()</TT> which adds 
its given argument to the actual <TT>Int</TT> object. Given this new definition,
we can define a new function <TT>increment_all_by()</TT>:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">void</SPAN> increment_all_by(vector&#60;Int&#62; &#38;vi, Int i) {
  for_each(vi.begin(), vi.end(), bind2nd(mem_fun_ref((Int&#38; (Int::*)(Int))&#38;Int::add), i));
}
</PRE>
<TR>
</TABLE>
<BR>

Due to our changes from the last section, this will work as expected. But if 
we decide to change the definition of <TT>add()</TT> into:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;">Int&#38; add(Int&#38; i)       { _i+= i._i; <SPAN STYLE="color : maroon; ">return</SPAN> *<SPAN STYLE="color : maroon; ">this</SPAN>; }
</PRE>
<TR>
</TABLE>
<BR>

by converting its argument into a reference type, we will face new problems.
Note however that this is common use and considered to be good programming 
style in C++, especially for big objects. So what's wrong? Trying to compile
the function <TT>increment_all_by()</TT> will result in compiler error
similar to: ``reference to reference is not allowed''. 

<P>
First of all, a version of <TT>mem_fun_ref()</TT> is called, which is
parametrized  by a pointer to member of type 
``<TT>Int&amp; (Int::*)(Int&amp;)</TT>''. It creates a function object of
type <TT>mem_fun1_ref_t&lt; Int&amp;, Int, IntSPMamp;&gt;</TT>. 
<TT>mem_fun1_ref_t</TT> is derived from <TT>binary_function</TT> whereby
the base class <TT>binary_function</TT> is used only in order to declare the
types of the function arguments in a common way (see section <A HREF="adapter_binder.html#Binders">3</A> on 
page <A HREF="adapter_binder.html#binaryFunction"><IMG  ALIGN="BOTTOM" BORDER="1" ALT="[*]"
 SRC="file:/share/software/latex2html99b6/icons/crossref.gif"></A>). In this case <TT>binary_function</TT> will be
parametrized with ``<TT>&lt;Int, Int&amp;, IntSPMamp;&gt;</TT>'' resulting in 
<TT>first_argument_type</TT> being equal to <TT>Int</TT>,
<TT>second_argument_type</TT> being equal to <TT>Int&amp;</TT> and
the <TT>result_type</TT> being equal to <TT>Int&amp;</TT>.

<P>
<TT>bind2nd()</TT> in turn takes this <TT>mem_fun1_ref_t</TT> object as 
template parameter for the <TT>binder2nd</TT> object it will create. 
Unfortunately, the constructor of <TT>binder2nd</TT> takes as its second 
argument a reference of type <TT>Operation::second_argument_type</TT> where
<TT>Operation</TT> is the template argument of <TT>bind2nd()</TT>, in this
case <TT>mem_fun1_ref_t&lt;Int&amp;, Int, IntSPMamp;&gt;</TT>. But
the second argument of <TT>Operation</TT> already has the type 
<TT>Int&amp;</TT>. During the instantiation of <TT>binder2nd</TT> the compiler 
tries to get the reference of a reference to a <TT>Int&amp;</TT> object which 
leads to the compiler error presented above.

<P>
Again this is no STL problem, but a problem of the C++ reference mechanism.
While it is possible to take the address of an address in C++ and to
apply the dereference operator as many times as necessary, this is not
possible for references. As the compiler complained, references of references
are not possible in C++. Again, there are two solutions for the problem.
The first one is not to use references at all, but pass objects by value or
use pointer to objects for big objects. This may be unacceptable under certain
circumstances or simply impossible if the classes we use are encapsulated in
third party libraries.

<P>
The remaining solution is again the specialization of classes already present
in the STL, to fit our needs. In this case we need a special version of the
class <TT>binary_function</TT>, which hides the reference type of it's second
argument:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">template</SPAN> &#60;<SPAN STYLE="color : maroon; ">class</SPAN> Arg1, <SPAN STYLE="color : maroon; ">class</SPAN> Arg2, <SPAN STYLE="color : maroon; ">class</SPAN> Result&#62;
<SPAN STYLE="color : maroon; ">struct</SPAN> binary_function&#60;Arg1, Arg2&#38;, Result&#62; {
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Arg1 first_argument_type;
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Arg2 second_argument_type;
    <SPAN STYLE="color : maroon; ">typedef</SPAN> Result result_type;
};      
</PRE>
<TR>
</TABLE>
<BR>

With this definition of <TT>binary_function</TT> the type of the function 
objects second argument will be properly propagated to <TT>binder2nd</TT>,
where a reference of it can be taken. 
Note that in other cases, it can be useful to have a specialization which
hides the reference type of the first argument or from both arguments. 
So in fact a set of three specializations may be necessary to meet all 
requirements.

<P>
A third solution would be possible here as well, but it would require a change
of the STL. The constructor of <TT>binder2nd</TT> may be changed to take its 
second argument by value and not as a reference.

<P>
Once again it is interesting here to have a look into Stroustrups book.
In section 18.4.4.3 he brings the following example for pointer to function
adapters:

<P>

<TABLE BORDER="2" CELLSPACING="0" CELLPADDING="10" RULES="none" >

<TR>
<TD STYLE="color : black; background-color : white;" >
<PRE STYLE="margin-bottom : 0;"><SPAN STYLE="color : maroon; ">struct</SPAN> Record { <SPAN STYLE="color : red; ">/* ... */</SPAN> };

<SPAN STYLE="color : maroon; ">bool</SPAN> name_key_eq(<SPAN STYLE="color : maroon; ">const</SPAN> Record&#38;, <SPAN STYLE="color : maroon; ">const</SPAN> Record) { <SPAN STYLE="color : maroon; ">return</SPAN> true; }
<SPAN STYLE="color : maroon; ">bool</SPAN> ssn_key_eq(<SPAN STYLE="color : maroon; ">const</SPAN> Record, <SPAN STYLE="color : maroon; ">const</SPAN> Record&#38;) { <SPAN STYLE="color : maroon; ">return</SPAN> false; }

<SPAN STYLE="color : maroon; ">void</SPAN> f(list&#60;Record&#62; lr) {
  <SPAN STYLE="color : maroon; ">typedef</SPAN> <SPAN STYLE="color : maroon; ">typename</SPAN> list&#60;Record&#62;::iterator LI;
  LI p = find_if(lr.begin(), lr.end(), bind2nd(ptr_fun(name_key_eq), <SPAN STYLE="color : teal; ">"FOO"</SPAN>));
  LI q = find_if(lr.begin(), lr.end(), bind2nd(ptr_fun(ssn_key_eq), 123456));
}
</PRE>
<TR>
</TABLE>
<BR>

Besides a small typo, <TT>typename</TT> is allowed only in templates
([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](14.6#5)), this 
example will not work in general. This is because the two functions take theirs
arguments by reference. Consequently, the types of the arguments of the 
function object created by <TT>ptr_fun</TT> will be defined as reference types
as well (this again is done through simple derivation from 
<TT>binary_function</TT>). Thereupon any instantiation of <TT>binder2nd</TT> 
with one of these function objects created by <TT>ptr_fun</TT> will lead to a 
compilation error because it will force the 
compiler to create a reference from another reference. 

<P>

<H1><A NAME="SECTION00040000000000000000">
<SPAN CLASS="arabic">4</SPAN> Conclusion</A>
</H1>

<P>
Although standardized, it seems as if the C++ version of the STL is far 
from being complete and consistent. Although prized as a ``generic''
library, even its own components can't always be used together. This paper 
focused only on a small part of the STL, namely adapters and binders, but it
revealed some serious problems in their implementation in C++. As shown,
many of this problems can easily be solved by applying C++ techniques like 
template specialization. 

<P>
One reason for this unsatisfying situation might be the absence of fully
standard compliant compilers during the design of the library. As demonstrated,
even Stroustrup, the ``creator'' of C++, uses the STL in his book in a
canonical way, but without noticing that the real C++-STL would fail to 
meet his needs.

<P>
As a consequence, we must realize that such a complex library like the STL
cannot be implemented from scratch in such a complex language like C++.
Many problems in C++ itself like the asymmetry between functions and
function objects or the dubious references need special workarounds in the 
library. Therefore a lot of user interaction is needed.

<P>
Using the STL still can significantly improve your productivity. 
But it assumes both, an in deep understanding of the library concepts behind 
the STL and an in deep understanding of the language concepts of C++. 
Used with this in mind, the remaining inconsistencies
will hopefully be eliminated in the near future, resulting in a powerful and
clean library.

<P>

<H1><A NAME="SECTION00050000000000000000">
<SPAN CLASS="arabic">5</SPAN> Future work</A>
</H1>

<P>
It is desirable to analyze the whole C++-STL in order to remove remaining
problems. For that a specification language like Tecton ([<A
 HREF="adapter_binder.html#Tecton">Tecton</A>]) can
be useful. First steps in this area have been made in [<A
 HREF="adapter_binder.html#TecSTL">TecSTL</A>].

<P>
Another possibility may be to change the semantics of the reference declarator
in C++ in order to make it idempotent. That means a reference to a
reference to a type <TT>T</TT> would be resolved to a reference to <TT>T</TT>, 
thus eliminating the ``reference to reference is not allowed''-error.
This could be done only in the special case, where the reference to a reference
is introduced through a <TT>typedef</TT> or a template type argument.
The same technique is applied in the C++ language in order to ignore 
repeated <TT>const</TT> or <TT>volatile</TT> 
qualifiers ([<A
 HREF="adapter_binder.html#ANSI-CPP">ANSI-CPP</A>](7.1.5)).

<P>

<H2><A NAME="SECTION00060000000000000000">
Bibliography</A>
</H2><DL COMPACT><DD><P></P><DT><A NAME="AGL">AGL</A>
<DD>
Musser David R. and Stepanov Alexander, 
<I>``Ada Generic Library''</I>
Springer-Verlag, 1989

<P></P><DT><A NAME="ANSI-CPP">ANSI-CPP</A>
<DD>
ANSI/ISO Standard
<I>``International Standard ISO/IEC 14882 - 
                 Programming Language C++'' </I>
<BR>American National Standards Institute (ANSI), 1998
at: ftp://research.att.com/dist/stdc++/WP/ (1996 draft)

<P></P><DT><A NAME="Kapur">Kapur</A>
<DD>
Kapur D., Musser David R. and Stepanov Alexander,
<I>``Operators and Algebraic Structures''</I>
<BR>Proc. of the Conf. on Func. Progr. Languages and 
Comp. Arch., Portsmouth, New Hampshire, October 1981

<P></P><DT><A NAME="Lee-Step">Lee-Step</A>
<DD>
Lee, Meng and Stepanov, Alexander
<I>``The Standard Template Library''</I>
<BR>at: http://www.cs.rpi.edu/&nbsp;musser/doc.ps

<P></P><DT><A NAME="Musser">Musser</A>
<DD>
Musser David R. and Stepanov Alexander,
<I>``A Library of Generic Algorithms in Ada''</I>
<BR>Proc. of the 1987 ACMSIGAda International Conference, Boston, 
December 1987

<P></P><DT><A NAME="SGI-STL">SGI-STL</A>
<DD>
<I>``The STL Implementation of Silicon Graphics''</I>
at: http://www.sgi.com/Technology/STL/

<P></P><DT><A NAME="Strou97">Strou97</A>
<DD>
Stroustrup, Bjarne. 
<I>``The C++ Programming Language. Third edition.'' </I>
Addison Wesley, 1997

<P></P><DT><A NAME="TecSTL">TecSTL</A>
<DD>
Musser David R.
<I>``Tecton Description of STL Container and Iterator Concepts''</I>
<BR>Wilhelm-Schickard-Institute f&#252;r Informatik, University of 
T&#252;bingen, 1998 (unpublished)

<P></P><DT><A NAME="Tecton">Tecton</A>
<DD>
Kapur D., Musser David R. and Stepanov Alexander,
<I>``Tecton: a framework for specifying and verifying generic
system components''</I>,
Rensselaer Polytechnic Inst., Computer Science Technical Report
92-20, 1992
</DL>

<P>

<H1><A NAME="SECTION00070000000000000000">
About this document ...</A>
</H1>
 <STRONG>Adapters and Binders - Overcoming problems
<BR>in the design and 
       implementation of the C++-STL</STRONG><P>
This document was generated using the

<A HREF="http://www-dsed.llnl.gov/files/programs/unix/latex2html/manual/"><STRONG>LaTeX</STRONG>2<tt>HTML</tt></A>
 translator Version 99.2beta6 (1.42)
<BR>and <A HREF=http://www-ca.informatik.uni-tuebingen.de/people/simonis/progdoc/progdoc.htm><STRONG><tt>Prog</tt>DOC</STRONG></A> the Program Documentation System
<P>
Copyright &#169; 1993, 1994, 1995, 1996,
<A HREF="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos Drakos</A>, 
Computer Based Learning Unit, University of Leeds.
<BR>Copyright &#169; 1997, 1998, 1999,
<A HREF="http://www.maths.mq.edu.au/~ross/">Ross Moore</A>, 
Mathematics Department, Macquarie University, Sydney.
<P>
The command line arguments were: <BR>
 <STRONG>latex2html</STRONG> <TT>-html_version 4.0 -split 0 -show_section_numbers -no_navigation -no_footnode -image_type gif -numbered_footnotes adapter_binder.tex</TT>
<P>
The translation was initiated by  on 
[1]<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot477">... Simonis</A><A NAME="foot477"
 HREF="adapter_binder.html#tex2html1"><SUP><SPAN CLASS="arabic">1</SPAN></SUP></A>
<DD>
  Fakult&#228;t f&#252;r Informatik, Arbeitsbereich Computer Algebra, Sand 13, 
  72076 T&#252;bingen, Germany,
  e-mail: simonis@informatik.uni-tuebingen.de
  

<DT><A NAME="foot1315">... it</A><A NAME="foot1315"
 HREF="adapter_binder.html#tex2html2"><SUP><SPAN CLASS="arabic">2</SPAN></SUP></A>
<DD>It must be stated here that the
STL is in fact older then C++ since it evolved from the ADA Generic 
Library [<A
 HREF="adapter_binder.html#AGL">AGL</A>]. The Ada Generic library in turn based on the ideas of its 
authors on generic programming which go back to the early '80th ([<A
 HREF="adapter_binder.html#Kapur">Kapur</A>], 
[<A
 HREF="adapter_binder.html#Musser">Musser</A>]). In contrast to this, the C++ implementation of the STL was 
incorporated into the C++ standard at a relatively late stage of the 
standardization process.

</DL><BR> <HR>
<ADDRESS>
<I> <BR>
2000-02-28</I>
</ADDRESS>
</BODY>
</HTML>

--=-GvwyjtNOARVzHhioIuI8--