///
/// ##################################################
/// If NULL pointer is unavoidable, use SharedPtrNull.
/// Regular SharedPtr will malfunction if given NULL.
/// ##################################################
///
/// Interface:
/// ----------
/// SharedPtr( void ); // default ctor constructs a new T
/// SharedPtrNull( void); // -or- default ctor constructs NULL pointer
/// SharedPtr( T* obj );
/// SharedPtr( const SharedPtr<T>& src );
/// ~SharedPtr();
/// SharedPtr<T>& operator=( const SharedPtr<T>& src );
/// SharedPtr<T>& operator=( T* obj );
/// T* operator->( void ) const;
/// T& operator*( void ) const;
/// bool operator==( const SharedPtr& other ) const;
/// bool operator!=( const SharedPtr& other ) const;
/// bool operator==( const T* obj ) const;
/// bool operator!=( const T* obj ) const;
/// T* PTR();
/// T& REF();
/// const T* CONST_PTR();
/// const T& CONST_REF();
///
/// Overview:
/// ---------
/// Shared is a base class that provides storage for a reference-count.
/// Shared itself is a NOP. Rather, objects to be reference-counted are given
/// to a SharedPtr which maintains the reference-count.
///
/// SharedPtr will own the object and is responsible for deleting the object.
/// Sharing an object is done by copying a SharedPtr which increments
/// the reference-count (in the Shared base part of the object).
/// When a SharedPtr is deleted, ~SharedPtr decrements the reference-count
/// and deletes the object when the count falls to zero.
///
/// Usage:
/// ------
/// Sharing an object is done by copying SharedPtr objects.
/// Copying a SharedPtr increments a reference count of the object being shared.
///
/// SharedPtr<Object> shared1( new Object );
/// SharedPtr<Object> shared2 = shared1; // copy constructor
///
/// Passing a SharedPtr to a function is implicit copying,
/// so the caller and callee shares the object.
/// A SharedPtr should be passed by value (not as a pointer/reference):
///
/// void Func( SharedPtr<Object> obj ); // right
/// void Func( SharedPtr<Object>& obj ); // wrong, inhibits necessary copying method
///
/// Directly assigning a SharedPtr with a pointer unshares one count of the outgoing object,
/// and resets the SharedPtr's reference count to 1 for the incoming object.
///
/// SharedPtr<Object> ptr1( new Object );
/// SharedPtr<Object> ptr2 = ptr1; // ptr1 and ptr2 share one Object (refCnt=2)
/// ptr2 = new Object; // ptr2 points to different Object (refCnt=1, refCnt=1)
///
/// const SharedPtr example:
///
/// SharedPtr<const Object> objc = new Object;
/// SharedPtr<Object> obj = new Object;
/// objc = obj; // ok (unless const object is supposed to be undeletable)
/// obj = objc; // won't compile
///
/// SharedPtr can effectively transfer ownership to caller:
///
/// SharedPtr<Object>
/// Producer( void )
/// {
/// SharedPtr<Object> obj = new Object;
/// obj->AddData(..);
/// ...
/// return obj;
/// }
///
/// A Shared object can be converted to a raw pointer
/// and then converted back to a SharedPtr variable.
/// This is very useful for a Visitor pattern which ordinarily
/// visits nodes in terms of raw pointers for speed, but rarely
/// needs to retain a reference-counted pointer to a node.
///
/// class Node : public Shared { };
///
/// class Visitor
/// {
/// void Visit( Node& node )
/// {
/// if ( node == sought )
/// {
/// // Can be thought of as a conversion from Node* to SharedPtr<Node>.
/// // Actually invokes SharedPtr::operator=(T*) which increases ref cnt.
/// mMatch = &node;
/// }
/// }
///
/// private:
/// SharedPtr<Node> mMatch;
/// };
///
/// Examples:
/// ---------
/// Instead of copying a 1MB pixmap requiring explicit memory management...
///
/// class Pixmap
/// {
/// uint8* GetBuf();
/// };
///
/// class Object
/// {
/// Object( Pixmap& pixmap )
/// {
/// mBuf = new uint8[pixmap.GetBufLen()]; // new array
/// memcpy( mBuf, pixmap.GetBuf(), pixmap.GetBufLen() ); // copy array
/// }
/// ~Object()
/// {
/// delete[] mBuf; // free array
/// }
/// uint8* mBuf;
/// };
///
/// ...using SharedPtr is way faster and simpler/safer as delete is eliminated:
///
/// class Pixmap
/// {
/// SharedPtr< Array<uint8> > GetBuf(); // shared array
/// };
///
/// class Object
/// {
/// Object( Pixmap& pixmap )
/// {
/// mBuf = pixmap.GetBuf(); // SharedPtrArr assignment is fast
/// }
/// ~Object() // dtor now does nothing
/// {
/// }
/// SharedPtr< Array<uint8> > mBuf; // shared array
/// };
///
/// An individual Shared object is interchangable between the variants of SharedPtr.
/// --------------------------------------------------------------------------------
/// The Shared object is independent of the SharedPtr that encapsulates it.
/// By using PTR(), a Shared can be extract from one kind of SharedPtr
/// and exchanged with another kind of SharedPtr.
///
/// SharedPtr<Data> data = new Data;
/// Producer producer( data.PTR() );
/// class Producer
/// {
/// Producer( SharedPtrNull<Data> data ); // Shared interchanged as SharedPtrNull
/// };
///
/// SharedPtrNull:
/// --------------
/// Regular SharedPtr must be optimal since it is extremely frequent.
/// If a NULL SharedPtr is possible and unavoidable, use the slower SharedPtrNull.
/// The same Shared object can be interchanged in a SharedPtr or SharedPtrNull
/// (as long as the value isn't NULL at run-time of course).
///
/// SharedPtrNull can point to abstract objects (unlike SharedPtr which
/// requires a default ctor which abstract classes lack).
///
/// An example of an unavoidable case where SharedPtr has to be NULL (interimly):
/// class Font
/// {
/// //SharedPtr<Texture> mTexture; // WRONG! SharedPtr ctor will crash!
/// SharedPtrNull<Texture> mTexture; // ok, SharedPtrNull can handle NULL
/// };
/// Font::Font( const FontDesc& desc, SafePtr<Gui> gui )
/// : mTexture(NULL)
/// {
/// [load .tga file]
/// mTexture = new Texture( targa, Texture::eMipmap_ON );
/// }
///
/// Rules and pitfalls:
/// -------------------
/// - Ways affecting the reference-count:
///
/// - passed as an arg
/// - returned
/// - constructed/destructed as a class member
/// - reassigned with a new object or another SharedPtr (src SharedPtr affected too)
/// - copied directly
/// - copied indirectly (as a member of a copyable class, container element, etc)
///
/// - Be aware that once a Shared object is encapsulated in a SharedPtr,
/// it becomes subject to automatic deletion by SharedPtr.
///
/// - Transferring ownership vs. sharing ownership:
///
/// SharedPtr is usually for sharing ownership, but it can be used to transfer ownership.
///
/// class Object : public Shared
/// {
/// // share ownership:
/// SharedPtr<Buffer> GetBuffer( void ) { return mBuffer; }
/// SharedPtr<Buffer> mBuffer;
///
/// // transfer ownership:
/// SharedPtr<Buffer> GetBuffer( void ) { return new Buffer; }
///
/// // WRONG/BUG (see below):
/// SharedPtr<Buffer> GetBuffer( void ) { return mBuffer; }
/// Buffer* mBuffer;
/// };
///
/// - PITFALL: A Shared, as a class member, must be encapsulated in SharedPtr:
///
/// Otherwise, as an actual member or a raw pointer, a Shared object
/// will initially have a zero reference-count. But the the class instance
/// implicitly references it. Any accessor method in the class that
/// returns it as a SharedPtr can may prematurely destroy it.
/// Though not recommended, if a Shared needs to be an actual member,
/// the class ctor can use Shared::IncRefCnt() to account for its reference.
///
/// class Node : public Shared
/// {
/// };
/// class Graph
/// {
/// SharedPtr<Node> GetRoot( void ) { return mRoot; }
///
/// Node* mRoot; // WRONG
/// Node mRoot; // WRONG
/// SharedPtr<Node> mRoot; // ok
/// };
///
/// - Don't blindly change T* to SharedPtr<T>:
///
/// Buffer sBuffer;
/// < Buffer* GetBuffer( void ) // original code
/// > SharedPtr<Buffer> GetBuffer( void ) // revised code
/// {
/// return sBuffer; // oops: implicitly converted to SharedPtr and deleted!
/// }
///
/// - Pitfalls in replacing raw pointers with SharedPtr:
///
/// < Object* mObject;
/// > SharedPtr<Object> mObject;
/// delete mObject; mObject = new Object; // renew idiom
///
/// SharedPtr::operator=() will malfunction by try freeing the deleted mObject.
/// Correction is to reassign SharedPtr without deleting.
///
/// SharedPtr<Object> mObject;
/// mObject = new Object; // reassign SharedPtr
///
/// Design notes:
/// -------------
/// Disadvantages are that SharedPtr intrusively requires deriving from Shared
/// and wastes an int in objects that aren't actually shared.
/// But the advantage is speed: the reference-count is allocated along with
/// the object, as opposed to having a separately allocated reference-count.
/// This advantage becomes important when lots of small objects are shared
/// and frequently created.
///
///