Jason Stredwick

jason.stredwick@gmail.com

Current Residence:
Bothell, WA 98011
me


Home
CV / Resume
Masters Work
WhirlingDervish
Programming
   Projects
   Various Code
     References
     Quantity/Builtin types
     Endian
     Type
     Functor
     Comm
   Additional
   Ideas
Misc. Ideas
Personal

Summary:


After many frustrating instances where I wanted to change a reference, I decided to try my hand at resolving this issue. First, I found that a reference can be conditionally assigned by using the ?: operator, at least in g++4 and Visual Studio 2005, if not potentially others. For example:

int x = 25;
int y = 37;
int &r1 = (x < y) ? x : y;
x = 45;
int &r2 = (x < y) ? x : y;
cout << r1 << " " << r2 << endl;

The are many situations that arise where I would like to be able to change a reference. One such situation is when I want to assign a reference based on user input or system state.

Another situation is when I want to store a reference as class member data rather than a pointer. This situation can arise from the requirement to have a non-null handle to some instantiated object. A pointer lacks certain guarantees and thus you have to constantly check to make sure it maintains its non-null status. A reference on the other hand guarantees that if it was initialized, it is non-null. There are exceptions, such as those rare occasions when you assign allocated memory to a reference and then delete the memory. However, this is a problem for standard reference variables as well.

Finally, it may be advantageous in the future to have a reference as a user defined class rather than a builtin type.

To find a solution to this problem, I thought I would try my hand at recreating a reference in the form of a class, and then extend it such that the reference itself can change.
These classes follow:

Ref.h
ReRef.h
RefTest.cpp (A test/sample program) There are commented out lines that say Compiler Error in the test. If you uncomment them, they should give you a compiler error. There is a potential problem if they do not give an error, and I consider the lack of error to violate the correct workings of the class.

The Ref class is meant to be a transparent replacement of an actual reference.
* The Ref class must be initialized with a reference or another Ref.
* Assignment changes the value of the reference, not what it points to.
* There are casting operators to the actual reference of the encapsulated type.
* There is an address operator which returns a pointer to the encapsulated data.
* Due to the possible need to have the address of the Ref class itself, there is the Address method.

The ReRef class is the same as the Ref class, except it allows the reference to change by calling the Reassign method. Also, because it inherits from Ref, it can be constructed and reassigned with a Ref, but not vice versa.

Source Code

Ref.h

/*

 * Copyright 2006 Jason Stredwick.

 * Distributed under the Boost Software License, Version 1.0. (See
 * LICENSE information at the bottom of this file or the copy at
 * http://www.boost.org/LICENSE_1_0.txt)

 */

#ifndef __Ref_h__
#define __Ref_h__

/*

 * Ref is intended to be the equivalent to a reference and transparent to
 *   the user.  It must be initialized with a reference or another Ref.
 *   Assignment changes the value of its data not what it is pointing to.
 *   The casting operators allow for seemless use of this class with global
 *   operators.
 * Note that the cast operator may give a warning on older compilers.
 *   This class was verified on g++4 and visual studio 2005.

 * Jason Stredwick May 7, 2006
 *   Added typedef T type as public member.  Also, realized and tested that
 *   boost::addressof works for determining the address of Ref too, not just
 *   the member method.  However, unless one is using the older MSVC
 *   the include hierarchy can be removed completely.

 * Jason Stredwick May 5, 2006
 *   Realized I needed a way to get a pointer of the Ref<T> variable, so
 *   I created the Address method.

 * Jason Stredwick May 5, 2006
 *   Figured out how I wanted to handle Ref<const T> and const Ref<T>.
 *     Const references are done ther with const Ref<T>,
 *     const Ref<const T>, or Ref<const T>.
 *   Added a const version of operator&.
 *   Removed test for self in operator=, which is not necessary.

 * Jason Stredwick April 6, 2006 Finalized first version of Ref.

 */

template <typename T>
class Ref
{
protected:
  T *d_t;

public:
  typedef T type;

private:
  // No default construction
  Ref(void);

public:
  Ref(T &t)            : d_t(&t)    { return; }
  Ref(const Ref<T> &r) : d_t(r.d_t) { return; }

  ~Ref(void) { d_t = 0; return; }

  // Assignment operators
  T &operator=(const Ref<T> &r) {
    *d_t = *(r.d_t);
    return *d_t;
  }

  T &operator=(const T &t) { *d_t = t; return *d_t; }

  // Address operator
  const T * operator&() const { return d_t; }
        T * operator&()       { return d_t; }

  // Cast operators
  // Allows for seemless use with global operators, though
  //   prior to g++3.3, may give warning
  operator const T &() const { return *d_t; }
  operator       T &()       { return *d_t; }

  const Ref *Address(void) const { return this; }
        Ref *Address(void)       { return this; }
};

#endif

/*

 * Boost Software License - Version 1.0 - August 17th, 2003

 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:

 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.

 */


ReRef.h

/*

 * Copyright 2006 Jason Stredwick.

 * Distributed under the Boost Software License, Version 1.0. (See
 * LICENSE information at the bottom of this file or the copy at
 * http://www.boost.org/LICENSE_1_0.txt)

 */

#ifndef __ReRef_h__
#define __ReRef_h__

/*

 * The ReRef class is based on the Ref class.  Ref is intended to be the
 *   equivalent to a reference and transparent to the user.  It must be
 *   initialized with a reference, Ref, or ReRef.  Assignment changes
 *   the value of its data not what it is pointing to.  The casting
 *   operators allow for seemless use of this class with global operators.
 * The ReRef class is exactly the same as the Ref class but includes one
 *   additional feature, the ability to change what the reference points
 *   to.  The Reassign method is just like the constructors, it takes only
 *   a variable reference, a Ref, or a ReRef.
 * Note that the cast operator may give a warning on older compilers.
 *   This class was verified on g++4 and visual studio 2005.

 * Jason Stredwick May 5, 2006
 *   Realized I needed a way to get a pointer of the Ref<T> variable, so
 *   I created the Address method.

 * Jason Stredwick May 5, 2006
 *   Figured out how I wanted to handle ReRef<const T> and const ReRef<T>.
 *     Const references are done ther with const ReRef<T>,
 *     const ReRef<const T>, or ReRef<const T>.
 *   Added a const version of operator&.
 *   Removed test for self in operator=, which is not necessary.

 * Jason Stredwick April 18, 2006 Modified ReRef to inherit Ref in order
 *   to handle the implicit construction of one with the other.

 * Jason Stredwick April 6, 2006 Finalized first version of Ref and ReRef.

 */

#include "Ref.h"

template <typename T>
class ReRef : public Ref<T>
{
private:
  // No default construction
  ReRef(void);

public:
  ReRef(T &t)              : Ref<T>(t) { return; }
  ReRef(const Ref<T> &r)   : Ref<T>(r) { return; }
  ReRef(const ReRef<T> &r) : Ref<T>(r) { return; }

  ~ReRef(void) { return; }

  // Assignment operators
  T &operator=(const ReRef<T> &r)
  {
    *Ref<T>::d_t = *(r.Ref<T>::d_t);
    return *Ref<T>::d_t;
  }

  T &operator=(const Ref<T> &r)
  {
    *Ref<T>::d_t = *(r.Ref<T>::d_t);
    return *Ref<T>::d_t;
  }

  T &operator=(const T &t)
  {
    *Ref<T>::d_t = t;
    return *Ref<T>::d_t;
  }

  // Address operator
  const T * operator&() const { return Ref<T>::d_t; }
        T * operator&()       { return Ref<T>::d_t; }

  // Cast operators
  // Allows for seemless use with global operators, though
  //   prior to g++3.3, may give warning
  operator const T &() const { return *Ref<T>::d_t; }
  operator       T &()       { return *Ref<T>::d_t; }

  const ReRef *Address(void) const { return this; }
        ReRef *Address(void)       { return this; }

  void Reassign(T &t)              { Ref<T>::d_t = &t;    return; }
  void Reassign(const Ref<T> &r)   { Ref<T>::d_t = r.d_t; return; }
  void Reassign(const ReRef<T> &r) { Ref<T>::d_t = r.d_t; return; }
};

#endif

/*

 * Boost Software License - Version 1.0 - August 17th, 2003

 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:

 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.

 */