Listing 2 (refptr.hpp)

// refptr.hpp - Macros for RefCntPtrs
//   These macros simplify the process of
// creating a new reference count pointer
// class for a new class type - instead of
// copying an existing one and changing the
// names with a text editor, the
// preprocessor is used to substitute the
// appropriate names. This is basically an
// attempt to emulate class templates, until
// C++ compilers that implement templates
// are available.
//
//   There are two primary macros here - the
// first is the DECLARE macro, for the class
// declaration and inline functions, i,e.
// the stuff usually found in the ".hpp"
// file. The DEFINE macro contains the
// definition of the non-inline member
// functions - the stuff usually found in
// the ".cpp" file.
//
//   To use these, simply create a class
// derived from RefCntItem, then put a
// RefCntPtrDECLARE() in an appropriate
// header file and a RefCntPtrDEFINE() in
// appropriate definition file (the class
// name is substituted for 'type').

#ifndef RefCntPtr_MACROS
 #define RefCntPtr_MACROS

 // this is used to create a name for
 // the class being defined, by
 // concatenating the original item
 // class name with "RefCntPtr"
 #define RefCntPtr(type) \
           type ## RefCntPtr

 // If DEBUG is defined, using a zero
 // pointer (an error) results in a
 // message. An exit() statement
 // might also be appropriate.

 #ifdef DEBUG
  #include <iostream.h>
  #define RefCntPtrDebug(type)       \
    if (0 == p_ptr)                  \
      cout << "ERROR - using 0 "     \
       "RefCntPtr to " #type "\n";
 #else
  #define RefCntPtrDebug(type)
 #endif


 #define RefCntPtrDECLARE(type)         \
 class RefCntPtr(type)                  \
  {                                     \
   private:                             \
                                  \
    type * p_ptr;                       \
                                  \
    void p_inc (void);                  \
                                  \
    void p_decAndDelete (               \
           type * dest);               \
                                  \
    void p_assign (                     \
           type * rVal);               \
   public:                              \
    RefCntPtr(type) (void)              \
      : p_ptr(0) {;};                   \
    RefCntPtr(type) (                   \
           const RefCntPtr(type)& in)  \
      : p_ptr (in.p_ptr)                \
      { p_inc(); };                     \
                                   \
    RefCntPtr(type) (                    \
           type * in)                  \
      : p_ptr(in)                       \
      { p_inc(); };                     \
                                   \
    ~RefCntPtr(type) (void)              \
      {p_decAndDelete(p_ptr);};          \
                                   \
    RefCntPtr(type) & operator = (        \
           RefCntPtr(type) & rVal)      \
      { p_assign (rVal.p_ptr);           \
        return *this; };                 \
                                   \
    RefCntPtr(type) & operator = (        \
           type * rVal)                 \
      { p_assign (rVal);                 \
        return *this; };                 \
                                   \
    type * operator -> (void)             \
      { RefCntPtrDebug(type)             \
        return p_ptr; };                 \
                                   \
    type & operator * (void)              \
      { RefCntPtrDebug(type)             \
        return *p_ptr; };               \
                                   \
    /* see note */                       \
    operator int (void)                  \
      {return (p_ptr != 0);};            \
                                  \
   private:                              \
    int operator == (RefCntPtr(type)&);  \
    int operator != (RefCntPtr(type)&);  \
    int operator <  (RefCntPtr(type)&);  \
    int operator <= (RefCntPtr(type)&);  \
    int operator >  (RefCntPtr(type)&);  \
    int operator >= (RefCntPtr(type)&);  \
 };
// operator int() allows comparisons such as
//   if (ptr) {},
// which is great. Unfortunately, it also
// allows comparisons such as
//   if (ptr1 == ptr2) {}
// to compile, but not as expected
// - operator int() is first applied to
// both sides, then the comparison is made
// with the resulting integers.
//
// This behavior can be overridden by
// declaring operator== - it has precedence
// here. Since I am working in MS-DOS with
// its segmented addressing, I didn't want
// pointer comparisons, (they don't always
// work) so I made operator== and its
// companions private. It would be simple
// to make them public and implement them
// if needed.


 #define RefCntPtrDEFINE(type)            \
 void RefCntPtr(type)::p_assign(          \
        type * rVal)                     \
                                    \
 /* the order of the calls to the       */ \
 /* increment and decrement functions   */ \
 /* is significant here. If the rVal    */ \
 /* and current value point to the same */ \
 /* place, we could delete the item and */ \
 /* then discover we need it.           */ \
  {                                        \
   type * tmp = p_ptr;                     \
   p_ptr =  rVal;                          \
   p_inc();                                \
   p_decAndDelete(tmp);                    \
  };                                       \
                                    \
 void RefCntPtr(type)::p_inc (void)        \
  {                                        \
   if (p_ptr)                              \
     p_ptr->incRefCnt();                  \
  };                                       \
                                    \
 void RefCntPtr(type)::p_decAndDelete (    \
        type * dest)                      \
  {                                        \
   if (dest)                               \
    {                                      \
     dest->decRefCnt();                    \
     if (0 == dest->refCnt())              \
       delete dest;                        \
    };                                      \
  };                                        \

#endif
// End of File