template<class T>
class Array2D {
public:
Array2D(int d1, int d2):dim(d2) {
data = (T*) malloc(sizeof(T) * d1 *d2);
}
class Array1D {
public:
Array1D (T* pd) : data(pd) { }
T& operator[] (int index) {
return *(data + index);
}
T* data;
};
Array1D operator[] (int index) {
return Array1D(data + dim * index);
}
private:
size_t dim;
T* data;
};
template<class T>
class RCPtr {
public:
RCPtr(T* realPtr = 0);
RCPtr(const RCPtr& rhs);
~RCPtr();
RCPtr& operator=(const RCPtr& rhs);
T* operator->() const;
T& operator*() const;
private:
T* pointee;
void init();
};
class RCObject {
public:
RCObject();
RCObject(const RCObject& rhs);
RCObject& operator=(const RCObject& rhs);
virtual ~RCObject() = 0;
void addReference();
void removeReference();
void markUnshareable();
bool isShareable() const;
bool isShared() const;
private:
size_t refCount;
bool shareable;
};
class String {
public:
String(const char *value = "");
class CharProxy {
public:
CharProxy(String& str, int index);
CharProxy& operator=(const CharProxy& rhs);
CharProxy& operator=(char c);
operator char() const;
const char * operator&() const;
char * operator&();
private:
String& theString;
int charIndex;
};
const CharProxy operator[](int index) const;
CharProxy operator[] (int index);
private:
struct StringValue :public RCObject {
char *data;
StringValue(const char *initValue);
StringValue(const StringValue& rhs);
void init(const char *initValue);
~StringValue();
};
RCPtr<StringValue> value;
};
RCObject::RCObject() : refCount(0), shareable(true) { }
RCObject::RCObject(const RCObject&) : refCount(0), shareable(true) { }
RCObject& RCObject::operator=(const RCObject &) { return *this; }
RCObject::~RCObject() { }
void RCObject::addReference() { ++refCount; }
void RCObject::removeReference() { if (--refCount == 0) delete this; }
void RCObject::markUnshareable() { shareable = false; }
bool RCObject::isShareable() const { return shareable; }
bool RCObject::isShared() const { return refCount > 1; }
template<class T>
void RCPtr<T>::init() {
if (pointee == 0) return;
if (pointee->isShareable() == false) {
pointee = new T(*pointee);
}
pointee->addReference();
}
template<class T>
RCPtr<T>::RCPtr(T* realPtr) : pointee(realPtr) { init(); }
template<class T>
RCPtr<T>::RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) { init(); }
template<class T>
RCPtr<T>::~RCPtr() { if (pointee) pointee->removeReference(); }
template<class T>
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs) {
if (pointee != rhs.pointee) {
T* oldPointee = pointee;
pointee = rhs.pointee;
init();
if (oldPointee) oldPointee->removeReference();
}
return *this;
}
template<class T>
T* RCPtr<T>::operator->() const { return pointee; }
template<class T>
T& RCPtr<T>::operator*() const { return *pointee; }
void String::StringValue::init(const char *initValue) {
data = new char[strlen(initValue) + 1];
strcpy(data, initValue);
}
String::StringValue::StringValue(const char *initValue) { init(initValue); }
String::StringValue::StringValue(const StringValue& rhs) { init(rhs.data); }
String::StringValue::~StringValue() { delete[] data; }
String::String(const char *initValue) : value(new StringValue(initValue)) { }
const String::CharProxy String::operator[](int index) const { return String::CharProxy(const_cast<String&>(*this), index); }
String::CharProxy String::operator[] (int index) { return String::CharProxy(*this, index); }
String::CharProxy::CharProxy(String& str, int index) : theString(str), charIndex(index) { }
String::CharProxy& String::CharProxy::operator=(const CharProxy& rhs) {
if (theString.value->isShareable()) {
theString.value = new StringValue(theString.value->data);
}
theString.value->data[charIndex] = rhs.theString.value->data[rhs.charIndex];
return *this;
}
String::CharProxy& String::CharProxy::operator=(char c) {
if (theString.value->isShared()) {
theString.value = new StringValue(theString.value->data);
}
theString.value->markUnshareable();
theString.value->data[charIndex] = c;
return *this;
}
String::CharProxy::operator char() const {
return theString.value->data[charIndex];
}
char * String::CharProxy::operator&() {
if (theString.value->isShared()) {
theString.value = new StringValue(theString.value->data);
}
return theString.value->data + charIndex;
}
const char * String::CharProxy::operator&() const {
return theString.value->data + charIndex;
}