#include <iostream>
using namespace std;
class ObutsuException
{
public:
operator char* () const { return "MuriPo!"; }
};
template <class T>
class Obutsu
{
protected:
T* pointer = NULL;
public:
Obutsu() {
cout << "Hungry!" << endl;
}
Obutsu(T* t) : pointer(t) {
if (pointer != NULL)
cout << "Eat! (" << pointer << ')' << endl;
else
cout << "Hungry!" << endl;
}
~Obutsu() {
if (pointer != NULL)
cout << "Poo! (" << pointer << ')' << endl;
else
cout << "Bye..." << endl;
}
void swap(Obutsu& obutsu) {
T *tmp;
tmp = pointer;
pointer = obutsu.pointer;
obutsu.pointer = tmp;
}
T* release() {
T *t = pointer;
pointer = NULL;
return t;
}
T* get() const { return pointer; }
operator bool () const { return (pointer != NULL); }
Obutsu(const Obutsu& otbutsu) {
throw ObutsuException();
}
Obutsu& operator = (const Obutsu& obutsu) const {
throw ObutsuException();
}
};
template <class T>
class Unko : public Obutsu<T>
{
public:
Unko() {}
Unko(T* t) : Obutsu<T>(t) {}
~Unko() { reset(NULL); }
T& operator * () const {
if (this->pointer == NULL) throw ObutsuException();
return *(this->pointer);
}
T* operator -> () const { return this->pointer; }
void reset(T* t = NULL) {
if (this->pointer == t) return;
if (this->pointer != NULL) delete this->pointer;
this->pointer = t;
}
};
template <class T>
class Unko<T[]> : public Obutsu<T>
{
public:
Unko() {}
Unko(T* t) : Obutsu<T>(t) {}
~Unko() { reset(NULL); }
T& operator [] (int n) const {
if (this->pointer == NULL) throw ObutsuException();
return *(this->pointer + n);
}
void reset(T* t = NULL) {
if (this->pointer == t) return;
if (this->pointer != NULL) delete [] this->pointer;
this->pointer = t;
}
};
class Value
{
private:
int value;
public:
Value(int v) : value(v) {}
~Value() { cout << "Oh! God!" << endl; }
int getValue() const { return value; }
void setValue(int v) { value = v; }
operator int () const { return value; }
};
int main() {
cout << "start" << endl;
try {
{
Unko<double> unchi;
cout << (bool)unchi << endl;
cout << unchi.get() << endl;
double *d = unchi.release();
unchi.reset(new double);
cout << (bool)unchi << endl;
cout << unchi.get() << endl;
if (d != NULL) delete d;
}
{
Unko<float> ecchi(new float);
cout << (bool)ecchi << endl;
ecchi.reset();
cout << (bool)ecchi << endl;
}
{
Unko<int> unko(new int);
Unko<int> poop(new int);
*unko = 100;
*poop = 200;
// unko = poop; //MuriPo!
unko.swap(poop);
cout << "unko: " << *unko << endl;
}
{
Unko<Value> val(new Value(777));
cout << "value: " << val->getValue() << endl;
val->setValue(999);
cout << "value: " << *val << endl;
}
{
Unko<int[]> arr(new int[10]);
for (int i = 0 ; i < 10; i++) {
arr[i] = i * i;
cout << "arr[" << i << "] = " << arr[i] << endl;
}
}
} catch (ObutsuException& ex) {
cout << ex << endl;
}
cout << "finish" << endl;
return 0;
}