#include <iostream>
using namespace std;
class ChinkoException
{
public:
operator char * () const { return "MuriPo!"; }
};
template <class T>
class Chinko
{
private:
T* pointer = NULL;
long *counter = NULL;
public:
Chinko() {}
Chinko(T* t) {
pointer = t;
counter = new long(1);
cout << "Erection!" << endl;
}
Chinko(const Chinko& chinko) {
pointer = chinko.pointer;
counter = chinko.counter;
(*counter)++;
}
~Chinko() { reset(); }
T& operator * () const {
if (pointer == NULL) throw ChinkoException();
return *(pointer);
}
operator bool () const { return (counter != NULL); }
T* operator -> () const { return pointer; }
T* get() const { return pointer; }
void swap(Chinko& chinko) {
long *cnt = counter;
T* t = pointer;
pointer = chinko.pointer;
counter = chinko.counter;
chinko.counter = cnt;
chinko.pointer = t;
}
void reset() {
if (counter == NULL) return;
(*counter)--;
if (*counter == 0) {
delete counter;
if (pointer != NULL) delete pointer;
cout << "Impotence..." << endl;
}
counter = NULL;
pointer = NULL;
}
void reset(T* t) {
reset();
pointer = t;
counter = new long(1);
}
long use_count() const {
if (counter == NULL) return 0;
return *counter;
}
bool unique() const {
if (counter == NULL) return false;
return (*counter == 1);
}
};
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 {
{
Chinko<int> chinko(new int);
cout << "chinko: " << *chinko << endl;
cout << "unique: " << chinko.unique() << endl;
cout << "count: " << chinko.use_count() << endl;
Chinko<int> bokki = chinko;
cout << "bokki: " << *bokki << endl;
*chinko = 100;
cout << "chinko: " << *chinko << endl;
cout << "bokki: " << *bokki << endl;
cout << "unique: " << chinko.unique() << endl;
cout << "count: " << chinko.use_count() << endl;
Chinko<int> shasei = bokki;
cout << "shasei: " << *shasei << endl;
cout << "unique: " << chinko.unique() << endl;
cout << "count: " << chinko.use_count() << endl;
bokki.reset();
cout << "unique: " << chinko.unique() << endl;
cout << "count: " << chinko.use_count() << endl;
}
{
Chinko<Value> val(new Value(777));
cout << val->getValue() << endl;
val->setValue(999);
cout << *val << endl;
val.reset(new Value(1111));
cout << *val << endl;
}
} catch (ChinkoException& ex) {
cout << ex << endl;
}
cout << "finish" << endl;
return 0;
}