//----------------------------------------------------------------------------
// Borland Class Library
// Copyright (c) 1992, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Various types of smart pointer templatized classes
//----------------------------------------------------------------------------
#if !defined(OWL_POINTER_H)
#define OWL_POINTER_H
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <new>
namespace owl {
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
//
// A pair of smart pointer template classes. Provides basic conversion
// operator to T*, as well as dereferencing (*), and 0-checking (!).
// These classes assume that they alone are responsible for deleting the
// object or array unless Relinquish() is called.
//
/// \addtogroup utility_group
/// @{
//
/// \class TPointerBase
// ~~~~~ ~~~~~~~~~~~~
/// Smart pointer base class. Provides basic conversion operator to T*, as well as
/// dereferencing (*), and 0-checking (!). This and derived classes assume that they alone are
/// responsible for deleting the object or array unless Relinquish() is called.
//
template<class T> class TPointerBase {
public:
T& operator *() {return *P;}
operator T*() {return P;}
int operator !() const {return P==0;}
T* Relinquish() {T* p = P; P = 0; return p;}
protected:
TPointerBase(T* pointer) : P(pointer) {}
TPointerBase() : P(0) {}
T* P;
private:
void* operator new(size_t) noexcept {return nullptr;} // prohibit use of new
#if !defined(BI_COMP_GNUC)
void operator delete(void* p) {((TPointerBase<T>*)p)->P=0;}
#endif
#if !defined(OWL5_COMPAT)
// Prohibit copying.
//
TPointerBase(const TPointerBase&);
TPointerBase& operator=(const TPointerBase&);
#endif
};
//
/// \class TPointer
// ~~~~~ ~~~~~~~~
/// Smart pointer to a single object. Provides member access operator ->
//
template<class T> class TPointer : public TPointerBase<T> {
public:
TPointer() : TPointerBase<T>() {}
#if !defined(OWL5_COMPAT)
explicit
#endif
TPointer(T* pointer) : TPointerBase<T>(pointer) {}
~TPointer() {delete this->P;}
TPointer<T>& operator =(T* src)
{
if (src == this->P) return *this; // same-pointer assignment
delete this->P;
this->P = src;
return *this;
}
T* operator->() {return this->P;} // Could throw exception if P==0
};
//
/// \class TAPointer
// ~~~~~ ~~~~~~~~~
/// Pointer to an array of type T. Provides an array subscript operator and uses
/// array delete[]
//
template<class T> class TAPointer : public TPointerBase<T> {
public:
TAPointer() : TPointerBase<T>() {}
#if !defined(OWL5_COMPAT)
explicit
#endif
TAPointer(T array[]) : TPointerBase<T>(array) {}
~TAPointer() {delete[] this->P;}
TAPointer<T>& operator =(T* src)
{
if (src == this->P) return *this; // same-pointer assignment
delete[] this->P;
this->P = src;
return *this;
}
T& operator[](int i) {return this->P[i];} // Could throw exception if P==0
T& operator[](size_t i) {return this->P[i];} // Could throw exception if P==0
};
//----------------------------------------------------------------------------
//
/// \class TEnvelope
// ~~~~~ ~~~~~~~~~
/// Envelope-letter type of smart pointers. In this implementation the envelope
/// acts as a smart pointer to a reference-counted internal letter. This allows
/// a lot of flexibility & safety in working with a single object (associated
/// with the letter) being assigned to numerous envelopes in many scopes. An 'A'
/// version is provided for use with arrays.
///
/// Use like:
/// \code
/// TEnvelope<T> e1 = new T(x,y,x); // e1 now owns a T in a letter
/// e1->Func(); // invokes Func() on the new T
/// Func(*e1); // passing a T& or a T this way
/// TEnvelope<T> e2 = e1; // e2 safely shares the letter with e1
///
/// TAEnvelope<T> e1 = new T[99]; // e1 now owns T[] in a letter
/// e1[i].Func(); // invokes Func() on a T element
/// Func(e1[i]); // passing a T& or a T this way
/// TAEnvelope<T> e2 = e1; // e2 safely shares the letter with e1
/// \endcode
//
template<class T> class TEnvelope {
public:
TEnvelope(T* object) : Letter(new TLetter(object)) {}
TEnvelope(const TEnvelope& src) : Letter(src.Letter) {Letter->AddRef();}
~TEnvelope() {Letter->Release();}
TEnvelope& operator =(const TEnvelope& src);
TEnvelope& operator =(T* object);
T* operator->() { return Letter->Object; }
T& operator *() { return *Letter->Object; }
private:
struct TLetter {
TLetter(T* object) : Object(object), RefCount(1) {}
~TLetter() { delete Object; }
void AddRef() { RefCount++; }
void Release() { if (--RefCount == 0) delete this; }
T* Object;
int RefCount;
};
TLetter* Letter;
};
//
//
//
class TVoidPointer {
public:
TVoidPointer( const void *p = 0 ) : Ptr(p) {}
TVoidPointer( const TVoidPointer& rp ) : Ptr(rp.Ptr) {}
const TVoidPointer& operator = ( const TVoidPointer& vp )
{ Ptr = vp.Ptr; return *this; }
const TVoidPointer& operator = ( const void *p )
{ Ptr = p; return *this; }
operator void *() const { return CONST_CAST(void *,Ptr); }
private:
const void *Ptr;
};
//
/// \class TComRefBase
// ~~~~~ ~~~~~~~~~~~
/// Encapsulation of OLE interface pointers
//
template<class T> class TComRefBase {
public:
operator T*() {return I;}
operator T**() {Clear(); return &I;}
int operator !() const {return I==0;}
void operator delete(void* p) {((TComRefBase<T>*)p)->I=0;}
protected:
TComRefBase(const TComRefBase<T>& i) : I(i.I) {if (I) I->AddRef();}
TComRefBase(T* i) : I(i) {}
TComRefBase() : I(0) {}
~TComRefBase() {Clear();}
void Clear() {if(I){I->Release(); I = 0;}}
T* I;
private:
// Prohibit use of operator new
//
void* operator new(size_t) noexcept {return nullptr;}
};
template<class T> class TComRef : public TComRefBase<T> {
public:
TComRef() : TComRefBase<T>() {}
TComRef(T* iface) : TComRefBase<T>(iface) {}
TComRef(const TComRef<T>& i) : TComRefBase<T>(i) {}
TComRef<T>& operator =(T* iface)
{
if (iface == this->I) return *this; // same-interface assignment
this->Clear();
this->I = iface;
return *this;
}
TComRef<T>& operator =(const TComRef<T>& i)
{
if (&i == this) return *this; // self-assignment
this->Clear();
if (i.I)
{
this->I = i.I;
this->I->AddRef();
}
return *this;
}
T* operator->() {return this->I;} // Could throw exception if I==0
T* operator->() const {return this->I;} // Could throw exception if I==0
//void** operator&() {this->Clear(); return (void**)&I;}
};
/// @}
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
template<class T>
TEnvelope<T>& TEnvelope<T>::operator =(const TEnvelope<T>& src)
{
if (&src == this) return *this; // self-assignment
Letter->Release();
Letter = src.Letter;
Letter->AddRef();
return *this;
}
template<class T>
TEnvelope<T>& TEnvelope<T>::operator =(T* object)
{
if (object == Letter->Object) return *this; // same-pointer assignment
Letter->Release();
Letter = new TLetter(object); // Assumes non-null! Use with new
return *this;
}
//
/// \class TAEnvelope
// ~~~~~ ~~~~~~~~~~
/// Envelope-letter type of smart pointer array. In this implementation the envelope
/// acts as a smart pointer to a reference-counted internal letter. This allows a
/// lot of flexibility & safety in working with a single object (associated with the
/// letter) being assigned to numerous envelopes in many scopes.
///
/// Use:
/// \code
/// TAEnvelope<T> e1 = new T[99]; // e1 now owns T[] in a letter
/// e1[i].Func(); // invokes Func() on a T element
/// Func(e1[i]); // passing a T& or a T this way
/// TAEnvelope<T> e2 = e1; // e2 safely shares the letter with e1
/// \endcode
template<class T> class TAEnvelope {
public:
TAEnvelope(T array[]) : Letter(new TLetter(array)) {}
TAEnvelope(const TAEnvelope& src) : Letter(src.Letter) {Letter->AddRef();}
~TAEnvelope() { Letter->Release(); }
TAEnvelope& operator =(const TAEnvelope& src);
TAEnvelope& operator =(T array[]);
T& operator[](int i) { return Letter->Array[i]; }
T* operator *() { return Letter->Array; }
private:
struct TLetter {
TLetter(T array[]) : Array(array), RefCount(1) {}
~TLetter() { delete[] Array; }
void AddRef() { RefCount++; }
void Release() { if (--RefCount == 0) delete this; }
T* Array;
int RefCount;
};
TLetter* Letter;
};
template<class T>
TAEnvelope<T>& TAEnvelope<T>::operator =(const TAEnvelope<T>& src)
{
if (&src == this) return *this; // self-assignment
Letter->Release();
Letter = src.Letter;
Letter->AddRef();
return *this;
}
template<class T>
TAEnvelope<T>& TAEnvelope<T>::operator =(T array[])
{
if (array == Letter->Array) return *this; // same-pointer assignment
Letter->Release();
Letter = new TLetter(array); // Assumes non-null! Use with new
return *this;
}
} // OWL namespace
#endif // OWL_POINTER_H
↑ V302 Member operator[] of 'TAPointer' class has a 32-bit type argument. Use memsize-type here.
↑ V302 Member operator[] of 'TAEnvelope' class has a 32-bit type argument. Use memsize-type here.
↑ V690 The 'TComRefBase' class implements a copy constructor, but lacks the copy assignment operator. It is dangerous to use such a class.