   Templates And Casting
  If I have a template class, a base class, a derived class, and a function that takes the template of the base:class Base { };class Derived : public Base { };template < typename T > class Pointer { };void Function ( Pointer < Base > B ) { }int main ( ){  Pointer < Derived > A;  Function ( A );}Is there any way I can make "Function ( A );" work automatically?Is this possible?Thanks!Greg   
  The way boost does this for it's smart pointer types is by giving Pointer a constructor ala:template < typename T > class Pointer {    T* internal;public:    template < typename U > Pointer( const Pointer<U>& other ): internal(other.internal) {}};;  You can do this without drilling into the implementation of your other Pointer template instances by assuming a uniform interface.Ie:template<typename T>class Pointer;class BasePointer{  template<typename T>  Pointer<T> create( T* ); // or whatever};template<typename T>class Pointer: public BasePointer{  T* internal;  friend class BasePointer;public:  template<typename U>  operator Pointer<U>()  {    BasePointer::create<U>( internal );  }};The fundamental difference is that it allows someone to specialise Pointer to use some variable other than T* internal.  So long as BasePointer::create< U > can create your Pointers from a U*, it works.  (I left that unimplemented).If your Pointer<T> can be trivially constructed from a T*, then you don't even need the BasePointer step -- but if Pointer<T> is anything like a reference counting pointer, then having it silently either take a reference to a T* or add a reference to a T* is fraught with issues.   ;  Awesome!I think I now have a pretty good reference counter. Any thing that can be counted must inherit "Pointable", but that's nbd. :)Thanks!Greg#pragma oncetemplate < typename T > class Pointer;// This is a nice reference counting pointer. Any class that you want to have be// to be pointed to must publicly inherit Pointable. Then a pointer to the object can be // made with Pointer<Thing>Name. Note that it must be constructed with the item // it is pointing to, so if making a dynamic object, use:// Pointer<Thing>Name = Pointer<Thing>::New (params)class Pointable{  template<typename T> friend class Pointer;  unsigned int NumRefs;  void IncRefs ( ) { NumRefs++; }  void DecRefs ( )  {    assert ( NumRefs > 0 );    NumRefs--;  }public:  Pointable ( )  : NumRefs ( 0 ) {}    // Copy constructor  Pointable ( const Pointable & NewP)  : NumRefs ( 0 ) {}};template < typename T > class Pointer{  template <typename TT> friend class Pointer;  T * Ref;public:  Pointer ( )   : Ref ( NULL ){}    Pointer ( T & obj )   : Ref ( & obj ) { //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }   Pointer ( T * obj )   : Ref ( obj ) { //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }   Pointer ( Pointer<T> & rVar )   : Ref ( rVar.Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  Pointer ( Pointer<T> * rVar )   : Ref ( rVar->Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  Pointer ( const Pointer<T> & rVar )   : Ref ( rVar.Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  Pointer ( const Pointer<T> * rVar )   : Ref ( rVar->Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  template < typename U >  Pointer ( const Pointer<U> & rVar )   : Ref ( rVar.Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  template < typename U >  Pointer ( const Pointer<U> * rVar )   : Ref ( rVar->Ref ){ //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }    ~Pointer ( )    { //fprintf(stderr, "%i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); if ( Ref != NULL )   {   Ref->DecRefs ( );   if ( Ref->NumRefs < 1 )   {//fprintf ( stderr, "   DELETED\n" );delete Ref;   } }    }  T * operator-> ( ) const    { return Ref; }   T * GetUnprotectedPointer ( ) const    { return Ref; }  T & GetUnprotectedRef ( ) const    { return *Ref; }  Pointer & operator = ( const Pointer<T> * rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "%i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( );   if ( Ref->NumRefs < 1 )   {//fprintf ( stderr, "   DELETED\n" );delete Ref;   } } Ref = rVar->Ref;  //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );   return *this;    }  Pointer & operator = ( const Pointer<T> & rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "%i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( );   if ( Ref->NumRefs < 1 )   {//fprintf ( stderr, "   DELETED\n" );delete Ref;   } } Ref = rVar.Ref;  //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );   return *this;    }  Pointer & operator = ( const T * rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "%i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( );   if ( Ref->NumRefs < 1 )   {//fprintf ( stderr, "   DELETED\n" );delete Ref;   } }   Ref = rVar;  //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );  return *this; }  Pointer & operator = ( const T & rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "%i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( );   if ( Ref->NumRefs < 1 )   {//fprintf ( stderr, "   DELETED\n" );delete Ref;   } }   Ref = &rVar;  //fprintf(stderr, "%i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );  return *this;    }  friend bool operator == ( const Pointer<T> & lhs,   const Pointer<T> & rhs )  {return ( lhs.Ref == rhs.Ref );   }  template <typename... Args> static  Pointer < T > New (Args&&... params)  {return Pointer < T > ( new T ( (params)... ) );  }  static  Pointer < T > New ( Pointer < T > Ti)  {return Pointer < T > ( new T ( *Ti.Ref ) );  }};template < typename T >class Newable{public:  template <typename... Args> static  Pointer < T > New (Args&&... params)  {return Pointer < T > ( new T ( (params)... ) );  }};;  Your code isn't remotely thread safe: and that is a rather important property.  Even if you don't need it yet, do the make-work to make it possible.Generally you want your inc and dec refs to return the value of the reference count immediately after you did the add/remove ref.Then the code that calls add/remove ref takes the return value, and makes a decision based on this.Second, I would move more of the implementation from the Pointer<> class to the Pointable<> class.  Make the Pointer<> class a simple RAII addref/removeref class that isn't in charge of deleting the Pointable<> object.Make the Pointable<> class have a virtual void DestroySelf() { delete this; } method.Have int DecRefs() do the following:int retval = --NumRefs;if (!retval) {  DestroySelf();}assert(retval >= 0);return retval;From the above, a fully thread-safe implementation is a mere "substitute operator -- for a thread-safe function" away.In addition, the DestroySelf() method allows you to create reference counted objects that pool themselves, have a pre-destructor phase, or a number of other tricks.  And by default, call delete.There is even the simple:template<typename Pointable>class OnStack: public Pointable {  void DestroySelf()  {    assert(false);  }public:  virtual ~OnStack()  {    assert(NumRefs == 1);  }};which creates an on-stack Pointable object type, in case you need it for whatever reason.  :);  Okay, I think I have it now that I can add thread locks in the future, whenever that time may come ( I still haven't decided between SDLthreads and pthreads ). I made the changes you recommended and it definitely feels more elegant. I had one bug that was really making me scratch my head, and that was that my objects were being deleted, but the destructors weren't being called, and that was because I didn't have an empty virtual destructor in Pointable!Do you see anything else that might potentially be a problematic?Thanks!Greg#pragma oncetemplate < typename T > class Pointer;// This is a nice reference counting pointer. Any class that you want to have able// to be pointed to must publically inheirit Pointable. Then a pointer to the object can be // made with Pointer<Thing>Name. Note that it must be constructed with the item // it is pointing to, or assigned. If making a dynamic object, use:// Pointer<Thing>Name = Pointer<Thing>::New (params)class Pointable{  template < typename T > friend class Pointer;  unsigned int IncRefs ( )   { return ++NumRefs; }    unsigned int DecRefs ( )   { int retval = --NumRefs; if (!retval) {   //fprintf ( stderr, "   DELETED\n" );   DestroySelf(); } assert(retval >= 0); return retval;    }  virtual void DestroySelf() { delete this; } protected:  unsigned int NumRefs;public:  Pointable ( )  : NumRefs ( 0 ) {}    // Copy constructor  Pointable ( const Pointable & NewP)  : NumRefs ( 0 ) {}  virtual ~Pointable ( )   {    assert ( NumRefs == 0);  }};template < typename T > class Pointer{  template <typename TT> friend class Pointer;  T * Ref;public:  Pointer ( )   : Ref ( NULL ){}    Pointer ( T & obj )   : Ref ( & obj ) { //fprintf(stderr, "&   i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }   Pointer ( T * obj )   : Ref ( obj ) { //fprintf(stderr, "*   %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }   Pointer ( const Pointer<T> & rVar )   : Ref ( rVar.Ref ){ //fprintf(stderr, "p&  %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  Pointer ( const Pointer<T> * rVar )   : Ref ( rVar->Ref ){ //fprintf(stderr, "p*  %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  template < typename U >  Pointer ( const Pointer<U> & rVar )   : Ref ( rVar.Ref ){ //fprintf(stderr, "pu& %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }  template < typename U >  Pointer ( const Pointer<U> * rVar )   : Ref ( rVar->Ref ){ //fprintf(stderr, "pu* %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);  Ref->IncRefs ( ); }    ~Pointer ( )    { //fprintf(stderr, "~   %i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); if ( Ref != NULL )Ref->DecRefs ( );    }  T * operator-> ( ) const    { return Ref; }   T * GetUnprotectedPointer ( ) const    { return Ref; }  T & GetUnprotectedRef ( ) const    { return *Ref; }  Pointer & operator = ( T * rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "=*  %i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( ); }   Ref = rVar;  //fprintf(stderr, "=*  %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );  return *this; }  Pointer & operator = ( T & rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "=&  %i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( ); }   Ref = &rVar;  //fprintf(stderr, "=&  %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );  return *this;    }  Pointer & operator = ( const Pointer<T> * rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "=p* %i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( ); } Ref = rVar->Ref;  //fprintf(stderr, "=p* %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );   return *this;    }  Pointer & operator = ( const Pointer<T> & rVar )    {  if ( Ref != NULL )   {   //fprintf(stderr, "=p& %i-- : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref);   Ref->DecRefs ( ); } Ref = rVar.Ref;  //fprintf(stderr, "=p& %i++ : %s : %p\n", Ref->NumRefs, typeid(this).name(), Ref); Ref->IncRefs ( );   return *this;    }  friend bool operator == ( const Pointer<T> & lhs,   const Pointer<T> & rhs )  {return ( lhs.Ref == rhs.Ref );   }  template <typename... Args> static  Pointer < T > New (Args&&... params)  {return Pointer < T > ( new T ( (params)... ) );  }  static  Pointer < T > New ( Pointer < T > Ti)  {return Pointer < T > ( new T ( *Ti.Ref ) );  }};template < typename T >class OnStack: public T, public Pointable {  void DestroySelf()  {    assert ( FALSE );  }public:  virtual ~OnStack ( )  {    assert ( NumRefs == 1 );  }};;  Your operator= sucks.  :)Here is the one true operator=(tm):foo& operator=(otherT const& other){  foo tmp = other;  this->swap(tmp);  return *this;}Well, actually, there are two true operator=s:foo& operator=(foo const& other){  foo tmp = other;  this->swap(tmp);  return *this;}template<typename T>foo& operator=(T const& other){  foo tmp = other;  this->swap(tmp);  return *this;}Now all you have to write is non-explicit copy constructors and a method swap(foo&) that swaps the content of two instances of foo.And operator= just works.Your constructors should be the following:Pointer() {};Pointer(Pointer const& other);template<typename U>Pointer(Pointer< U > const& other);template<typename U>Pointer(U* other);Your other constructors are a bad idea.//This operator:  T * operator->() const//and this operator:  T& operator*() const//should be implemented in terms of:  T * GetUnprotectedPointer ( ) const  T & GetUnprotectedRef ( ) constGetUnprotectedPointer should be renamed to "BorrowPointer", because that is what you are doing.Possibly you should support operator T* (and maybe operator U*) implicit casting.  This is useful when you have a function that doesn't know it is taking a reference counted object.  template <typename... Args> staticC++0x I assume?OnStack should assume the typed passed in was Pointable.You might want a T* ClonePointer() method, possibly private.  It makes a bunch of the rest of the reference counting code easier.Another useful one for auto pointer classes isT*& FillPtr() { Pointer tmp; this->swap(tmp); return Ref; }which works well with the interfaces that take a T** or the like and want to fill it.  But I suppose they can take a Pointer<T>* just as easily.   