#include <iostream>
#include <map>
#include <memory>
using namespace std;
template<class T, class A = allocator<T> >
class FooPtr
{
typedef T FOO, *LPFOO;
typedef A ALLO;
typedef map<LPFOO ,int> REFMAP, *LPREFMAP;
public:
FooPtr() : _ptr(NULL), id(counter()) {
cout << "FooPtr() : " << id << " ... " << _ptr << endl;
}
FooPtr(LPFOO ptr) : _ptr(ptr), id(counter()) {
if (_ptr) {
REFMAP& m = refmap();
cout << "FooPtr(FOO) : " << id << " ... " << _ptr
<< "[" << m[_ptr] << " -> " << (m[_ptr] + 1) << "]" << endl;
m[_ptr]++;
} else {
cout << "FooPtr(FOO) : " << id << " ... " << _ptr << endl;
}
}
FooPtr(const FooPtr& other) : _ptr(other._ptr), id(counter()) {
REFMAP& m = refmap();
if (m[_ptr]) {
cout << "FooPtr(FooPtr) : " << id << " ... " << _ptr
<< "[" << m[_ptr] << " -> " << (m[_ptr] + 1) << "]" << endl;
m[_ptr]++;
} else {
cout << "FooPtr(FooPtr) : " << id << " ... " << _ptr
<< "[" << m[_ptr] << " -> " << "???" << "]" << endl;
cout << "\t-instance is none!!" << endl;
_ptr = NULL;
}
}
~FooPtr() {
if (_ptr) {
REFMAP& m = refmap();
cout << "~FooPtr() : " << id << " ... " << _ptr
<< "[" << m[_ptr] << " -> " << (m[_ptr] - 1) << "]" << endl;
m[_ptr]--;
if (m[_ptr] == 0) {
m.erase(_ptr);
cout << "\t-begin of deallocate-" << endl;
//delete _ptr;
ALLO allo;
allo.destroy(_ptr);
allo.deallocate(_ptr, 0);
cout << "\t-end of deallocate-" << endl;
}
_ptr = NULL;
} else {
cout << "~FooPtr() : " << id << " ... " << _ptr << endl;
}
}
FOO& operator * () {
return *_ptr;
}
private:
LPFOO _ptr;
int id;
static int counter() {
static int c = 0;
return ++c;
}
static REFMAP& refmap() {
static REFMAP ref;
return ref;
}
};
class Hoge
{
public:
Hoge() : id(counter()) { cout << "Hoge: "<< id
<< " ... " << this << endl; }
~Hoge() { cout << "~Hoge: " << id
<< " ... " << this << endl; id = -id; }
operator int () {
return id;
}
private:
int id;
static int counter() {
static int c = 0;
return ++c;
}
};
FooPtr<Hoge> fuga(FooPtr<Hoge> h1) {
cout << "fuga: " << *h1 << endl;
FooPtr<Hoge> h2(new Hoge);
return h2;
}
FooPtr<Hoge>& piyo(FooPtr<Hoge>& h1) {
cout << "piyo: " << *h1 << endl;
FooPtr<Hoge> h2(new Hoge);
return h2;
}
int main() {
// your code goes here
Hoge hoge1;
Hoge *hoge2 = new Hoge;
FooPtr<Hoge> foo(new Hoge);
FooPtr<Hoge> bar(foo);
FooPtr<Hoge> zero;
cout << "----" << endl;
FooPtr<Hoge> baz = fuga(new Hoge);
cout << "----" << endl;
FooPtr<Hoge> p(new Hoge);
FooPtr<Hoge> foobar = piyo(p);
cout << "----" << endl;
cout << "hoge1 = " << hoge1 << endl;
cout << "hoge2 = " << *hoge2 << endl;
cout << "foo = " << *foo << endl;
cout << "bar = " << *bar << endl;
cout << "baz = " << *baz << endl;
// cout << "foobar = " << *foobar << endl; // Wrong Access!
cout << "****" << endl;
delete hoge2;
cout << "****" << endl;
return 0;
}