blob: da1c52e33f48be77279f084510d2cb4743b7d182 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @file Reference.hpp
*
*//* ----------------------------------------------------------------------- */
#ifndef MADLIB_REFERENCE_HPP
#define MADLIB_REFERENCE_HPP
namespace madlib {
namespace utils {
/**
* @brief A reference to type T that masquerades as being of type U.
*
* An an example, a masqueading reference could be used to use a double variable
* to store an integer value (which might be the most efficient solution to
* store a composite type of floating-point and integer values as a double
* array).
*/
template <typename T, typename U = T>
class Reference {
public:
Reference() : mPtr(NULL) { }
// FIXME: Is it better to have the const_cast in the mutable class
// and declare mPtr as const?
Reference(const T *inPtr) : mPtr(const_cast<T*>(inPtr)) { }
Reference& rebind(const T *inPtr) {
mPtr = const_cast<T*>(inPtr);
return *this;
}
/**
* @brief Return the value pointed to by the reference as type U
*/
operator U() const {
return static_cast<U>(*mPtr);
}
const T* ptr() const {
return mPtr;
}
const T& ref() const {
return *mPtr;
}
protected:
/**
* Defined but protected.
*/
Reference& operator=(const Reference&) {
return *this;
}
T *mPtr;
};
template <typename T, typename U = T>
class MutableReference : public Reference<T, U> {
typedef Reference<T, U> Base;
public:
MutableReference() { }
MutableReference(T *inPtr) : Base(inPtr) { }
/**
* @internal
* It is important to define this operator because C++ will otherwise
* perform an assignment as a bit-by-bit copy. Note that this default
* operator= would be used even though there is a conversion path
* through dest.operator=(orig.operator U())
*/
MutableReference& operator=(const MutableReference& inReference) {
return this->operator=(static_cast<const Base&>(inReference));
}
MutableReference& operator=(const Base &inReference) {
*mPtr = *inReference.ptr();
return *this;
}
MutableReference& operator=(const U &inValue) {
*mPtr = static_cast<T>(inValue);
return *this;
}
MutableReference& operator+=(const U &inValue) {
*mPtr += static_cast<T>(inValue);
return *this;
}
MutableReference& operator-=(const U &inValue) {
*mPtr -= static_cast<T>(inValue);
return *this;
}
U operator++(int) {
U returnValue = static_cast<U>(*mPtr);
*mPtr += static_cast<T>(1);
return returnValue;
}
MutableReference& operator++() {
*mPtr += static_cast<T>(1);
return *this;
}
T* ptr() {
return mPtr;
}
T& ref() {
return *mPtr;
}
protected:
using Base::mPtr;
};
} // namespace modules
} // namespace regress
#endif