Re: Templated containers of inherited objects
Roland Pibinger wrote:
On 17 Feb 2007 22:53:14 -0800, "=?iso-8859-1?q?Kirit_S=E6lensminde?="
<kirit.saelensminde@gmail.com> wrote:
On Feb 18, 2:12 am, rpbg...@yahoo.com (Roland Pibinger) wrote:
A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.
What is your definition of 'value' that makes you say that a pointer
isn't a value? After all a pointer *is* just an integer, but one which
is interpreted in a specific way (old x86 style far pointers
notwithstanding), but that is the same as many other value types too.
A pointer can be dereferenced, i.e. pointers have a specific
dereference operator.
In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.
I've come across this assertion a couple of times. To me the STL is a
fine bit of OO programming, but I can see where the functional view
comes into it too.
OO is characterized by inherited and polymorphic objects. STL neither
uses nor supports these.
Hm, I always felt that this is simply because pointers are not really what
we want when dealing with objects. What we want is something like a
reference that can be assigned and re-seated. Something like this:
template < typename T >
class smart_ref {
T * the_ptr;
public:
// maybe, we should not have this constructor !
smart_ref ( T * ptr )
: the_ptr ( ptr )
{}
smart_ref ( T & ref )
: the_ptr ( &ref )
{}
operator T & ( void ) {
return ( *the_ptr );
}
operator T const & ( void ) const {
return ( *the_ptr );
}
// these really want to be overloaded dot-operators:
T * operator-> ( void ) {
return ( the_ptr );
}
T const * operator-> ( void ) const {
return ( the_ptr );
}
};
With this, STL works to some extend. The amount of failure derives mostly
from the fact that we cannot overload the dot-operator (which is a real
shame).
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>
#include <ostream>
class X {
unsigned int the_ssn;
public:
X ( unsigned int ssn )
: the_ssn ( ssn )
{}
virtual
std::string name ( void ) const {
return ( "X" );
}
unsigned int ssn ( void ) const {
return ( the_ssn );
}
~X ( void ) {}
friend
bool operator< ( X const & lhs, X const & rhs ) {
return ( lhs.the_ssn < rhs.the_ssn );
}
};
struct Y : public X {
Y ( unsigned int ssn )
: X ( ssn )
{}
virtual
std::string name ( void ) const {
return ( "Y" );
}
virtual
~Y ( void ) {}
};
std::ostream & operator<< ( std::ostream & ostr,
X const & x ) {
return ( ostr << x.name() << "(" << x.ssn() << ")" );
}
typedef smart_ref<X> X_ref;
typedef std::vector<X_ref> X_vect;
int main ( void ) {
{
X a ( 333451234 );
X b ( 919113247 );
Y c ( 238648666 );
Y d ( 237986136 );
X e ( 879823769 );
X_vect xv;
xv.push_back( X_ref(a) );
xv.push_back( X_ref(b) );
xv.push_back( X_ref(c) );
xv.push_back( X_ref(d) );
xv.push_back( X_ref(e) );
std::sort( xv.begin(), xv.end() );
for ( X_vect::const_iterator iter = xv.begin();
iter != xv.end(); ++iter ) {
std::cout << *iter << '\n';
}
}
}
Maybe, it's not that STL does not want to work with OO-objects. Maybe, it's
just that pointers make for lousy OO-objects.
Best
Kai-Uwe Bux