#include <iostream>
#include <memory>
#include <map>
using namespace std;
class NullPtr_t
{
public:
NullPtr_t() : zero(NULL) {}
template< class T >
operator T* () const { return NULL; }
template< class T, class C >
operator T C::* () const { return NULL; }
private:
void operator &() const;
void *zero;
};
inline NullPtr_t getNullPtr() { return NullPtr_t(); }
#define nullptr getNullPtr()
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(nullptr) {
}
FooPtr(LPFOO ptr) : _ptr(ptr) {
if (_ptr == nullptr) {
return;
}
REFMAP& m = refmap();
m[_ptr]++;
}
FooPtr(const FooPtr& other) : _ptr(other._ptr) {
if (_ptr == nullptr) {
return;
}
REFMAP& m = refmap();
if (m[_ptr] == 0) {
_ptr = nullptr;
return;
// or throw Exception
}
m[_ptr]++;
}
~FooPtr() {
if (_ptr == nullptr) {
return;
}
REFMAP& m = refmap();
m[_ptr]--;
if (m[_ptr] == 0) {
ALLO allo;
allo.destroy(_ptr);
allo.deallocate(_ptr, 1);
}
_ptr = nullptr;
}
FOO& operator *() {
return *_ptr;
}
FooPtr& operator = (const FooPtr& other) {
clear();
_ptr = other._ptr;
if (_ptr != nullptr) {
REFMAP& m = refmap();
if (m[_ptr] == 0) {
_ptr = nullptr;
// or throw Exception
} else {
m[_ptr]++;
}
}
return *this;
}
FooPtr& operator = (const LPFOO foo) {
clear();
if (foo == nullptr) {
return *this;
}
// ALLO allo;
// _ptr = allo.allocate(1);
// allo.construct(_ptr, *foo);
_ptr = foo;
REFMAP& m = refmap();
m[_ptr]++;
return *this;
}
/*
FooPtr& operator = (const NullPtr_t&) {
clear();
return *this;
}
*/
void clear() {
if (_ptr == nullptr) {
return;
}
REFMAP& m = refmap();
m[_ptr]--;
if (m[_ptr] == 0) {
ALLO allo;
allo.destroy(_ptr);
allo.deallocate(_ptr, 1);
}
_ptr = nullptr;
}
LPFOO operator -> () {
return _ptr;
}
private:
LPFOO _ptr;
REFMAP& refmap() {
static REFMAP ref;
return ref;
}
};
class Hoge
{
public:
Hoge() : id(counter()) {
cout << "Hoge() : " << id << endl;
}
Hoge(const Hoge&) : id(counter()) {
cout << "Hoge(Hoge&) : " << id << endl;
}
~Hoge() {
cout << "~Hoge() : " << id << endl;
}
operator int () {
return id;
}
void print() {
cout << "Hoge method: " << id << endl;
}
private:
const int id;
static int counter() {
static int c = 0;
return ++c;
}
};
FooPtr<Hoge> getHoge() {
FooPtr<Hoge> temp(new Hoge);
return temp;
}
int main() {
// your code goes here
cout << "** begin of program **" << endl;
FooPtr<Hoge> hoge1(new Hoge);
{
cout << "-- test 1 --" << endl;
FooPtr<Hoge> empty;
empty = hoge1;
cout << "hoge1: " << *hoge1 << endl;
cout << "empty: " << *empty << endl;
}
{
cout << "-- test 2 --" << endl;
FooPtr<Hoge> hoge2(hoge1);
cout << "hoge1: " << *hoge1 << endl;
cout << "hoge2: " << *hoge2 << endl;
}
{
cout << "-- test 3 --" << endl;
FooPtr<Hoge> hoge3 = hoge1;
cout << "hoge1: " << *hoge1 << endl;
cout << "hgoe3: " << *hoge3 << endl;
}
{
cout << "-- test 4 --" << endl;
FooPtr<Hoge> hoge4 = hoge1;
hoge1 = nullptr;
cout << "hoge4: " << *hoge4 << endl;
}
{
cout << "-- test 5 --" << endl;
hoge1 = new Hoge;
cout << "hoge1: " << *hoge1 << endl;
}
{
cout << "-- test 6 --" << endl;
hoge1->print();
}
{
cout << "-- test 7 --" << endl;
getHoge();
hoge1 = getHoge();
}
cout << "** end of program **" << endl;
return 0;
}