fork download
  1. #include <iostream>
  2. #include <memory>
  3. #include <map>
  4.  
  5. using namespace std;
  6.  
  7. #define Msg1(msg) {cout << (msg) << endl;}
  8. #define Msg2(msg1,msg2) {cout << (msg1) << (msg2) << endl;}
  9. #define Msg2s(msg1,msg2,sp) {cout << (msg1) << (sp) << (msg2) << endl;}
  10.  
  11. #define DebugMode
  12.  
  13. #ifdef DebugMode
  14. # define DebugMsg1(msg) Msg1(msg)
  15. #else
  16. # define DebugMsg1(msg)
  17. #endif
  18.  
  19.  
  20. class NullPtr_t
  21. {
  22. public:
  23. NullPtr_t() : zero(NULL) {}
  24. template< class T >
  25. operator T* () const { return NULL; }
  26. template< class T, class C >
  27. operator T C::* () const { return NULL; }
  28. private:
  29. void operator &() const;
  30. void *zero;
  31. };
  32.  
  33. inline NullPtr_t getNullPtr() { return NullPtr_t(); }
  34. #define nullptr getNullPtr()
  35.  
  36. template< class T >
  37. class BasePtr
  38. {
  39. typedef BasePtr< T > ThisPtr;
  40.  
  41. virtual T* get() = 0;
  42. virtual T& ref() = 0;
  43.  
  44. friend bool operator == (ThisPtr& a, ThisPtr& b) {
  45. return a.get() == b.get();
  46. }
  47.  
  48. friend bool operator != (ThisPtr& a, ThisPtr& b) {
  49. return a.get() != b.get();
  50. }
  51. };
  52.  
  53. template< class T, class A = allocator< T > >
  54. class FooPtr : public BasePtr< T >
  55. {
  56. typedef T FOO, *LPFOO;
  57. typedef A ALLO;
  58. typedef map< LPFOO, int > REFMAP;
  59. typedef FooPtr< FOO , ALLO > ThisPtr;
  60.  
  61. private:
  62. LPFOO _ptr;
  63.  
  64. REFMAP& refmap() {
  65. static REFMAP refm;
  66. return refm;
  67. }
  68.  
  69. public:
  70.  
  71. FooPtr() : _ptr(nullptr) {
  72. }
  73.  
  74. FooPtr(const LPFOO foo) : _ptr(nullptr) {
  75. DebugMsg1( "FooPtr(LPFOO)" );
  76. reset(foo);
  77. }
  78.  
  79. FooPtr(const ThisPtr& other) : _ptr(nullptr) {
  80. DebugMsg1( "FooPtr(ThisPtr)" );
  81. copy(other);
  82. }
  83.  
  84. ~FooPtr() {
  85. clear();
  86. }
  87.  
  88. FOO& operator *() const { return *_ptr; }
  89.  
  90. operator LPFOO const () { return _ptr; }
  91.  
  92. LPFOO operator -> () const { return _ptr; }
  93.  
  94. LPFOO get() { return _ptr; }
  95.  
  96. FOO& ref() { return *_ptr; }
  97.  
  98. ThisPtr& operator = (const ThisPtr& other) {
  99. DebugMsg1( "ope = ThisPtr" );
  100. copy(other);
  101. return *this;
  102. }
  103.  
  104. ThisPtr& operator = (const LPFOO foo) {
  105. DebugMsg1( "ope = LPFOO" );
  106. reset(foo);
  107. return *this;
  108. }
  109.  
  110. void reset(const LPFOO foo) {
  111. clear();
  112. if (foo == nullptr) {
  113. return;
  114. }
  115.  
  116. _ptr = foo;
  117.  
  118. REFMAP& m = refmap();
  119. m[_ptr]++;
  120. }
  121.  
  122. void copy(const ThisPtr& other) {
  123. clear();
  124. _ptr = other._ptr;
  125. if (_ptr != nullptr) {
  126. REFMAP& m = refmap();
  127. if (m[_ptr]) {
  128. m[_ptr]++;
  129. } else {
  130. // missing
  131. _ptr = nullptr;
  132. // or throw Exception
  133. }
  134. }
  135. }
  136.  
  137. void clear() {
  138. if (_ptr == nullptr) {
  139. return;
  140. }
  141. REFMAP& m = refmap();
  142. m[_ptr]--;
  143. if (m[_ptr] == 0) {
  144. ALLO allo;
  145. allo.destroy(_ptr);
  146. allo.deallocate(_ptr, 1);
  147. }
  148. _ptr = nullptr;
  149. }
  150.  
  151. };
  152.  
  153.  
  154. class Hoge
  155. {
  156. public:
  157. Hoge() : id(counter()) {
  158. Msg2( "Hoge() : ", id );
  159. }
  160. Hoge(const Hoge&) : id(counter()) {
  161. Msg2( "Hoge(Hoge&) : ", id );
  162. }
  163.  
  164. ~Hoge() {
  165. Msg2( "~Hoge() : ", id );
  166. }
  167.  
  168. operator int () {
  169. return id;
  170. }
  171.  
  172. void print() {
  173. Msg2( "Hoge method : ", id );
  174. }
  175.  
  176. private:
  177. const int id;
  178. static int counter() {
  179. static int c = 0;
  180. return ++c;
  181. }
  182. };
  183.  
  184. FooPtr<Hoge> getHoge() {
  185. FooPtr<Hoge> temp(new Hoge);
  186. return temp;
  187. }
  188.  
  189. int main() {
  190. Msg1( "** begin of program **" );
  191.  
  192. FooPtr<Hoge> hoge1(new Hoge);
  193.  
  194. {
  195. Msg1( "-- test 1 --" );
  196. FooPtr<Hoge> empty;
  197.  
  198. empty = hoge1;
  199.  
  200. Msg2( "hoge1: ", *hoge1 );
  201. Msg2( "empty: ", *empty );
  202. }
  203.  
  204. {
  205. Msg1( "-- test 2 --" );
  206. FooPtr<Hoge> hoge2(hoge1);
  207.  
  208. Msg2( "hoge1: ", *hoge1 );
  209. Msg2( "hoge2: ", *hoge2 );
  210. }
  211.  
  212. {
  213. Msg1( "-- test 3 --" );
  214. FooPtr<Hoge> hoge3 = hoge1;
  215.  
  216. Msg2( "hoge1: ", *hoge1 );
  217. Msg2( "hgoe3: ", *hoge3 );
  218. }
  219.  
  220. {
  221. Msg1( "-- test 4 --" );
  222. FooPtr<Hoge> hoge4 = hoge1;
  223. hoge1 = nullptr;
  224.  
  225. Msg2( "hoge4: ", *hoge4 );
  226. }
  227.  
  228. {
  229. Msg1( "-- test 5 --" );
  230. hoge1 = new Hoge;
  231.  
  232. Msg2( "hoge1: ", *hoge1 );
  233. }
  234.  
  235. {
  236. Msg1( "-- test 6 --" );
  237.  
  238. hoge1->print();
  239. }
  240.  
  241. {
  242. Msg1( "-- test 7 --" );
  243.  
  244. getHoge();
  245.  
  246. hoge1 = getHoge();
  247. }
  248.  
  249. {
  250. Msg1( "-- test 8 --" );
  251.  
  252. Hoge *h1 = hoge1;
  253.  
  254. h1->print();
  255.  
  256. h1 = nullptr;
  257. }
  258.  
  259. {
  260. Msg1( "-- test 9 --" );
  261.  
  262. FooPtr<Hoge> f1(hoge1);
  263. FooPtr<Hoge> f2(new Hoge);
  264.  
  265. if (f1 == hoge1) {
  266. Msg1( "f1 == hoge1" );
  267. } else {
  268. Msg1( "not f1 == hoge1 (!?)" );
  269. }
  270.  
  271. if (f2 != hoge1) {
  272. Msg1( "f2 != hoge1" );
  273. } else {
  274. Msg1( "not f2 != hoge1 (!?)" );
  275. }
  276. }
  277.  
  278. {
  279. Msg1( "-- test 10 --" );
  280. FooPtr<Hoge> h3 = new Hoge;
  281. hoge1 = h3;
  282. }
  283.  
  284. Msg1( "** end of program **" );
  285. return 0;
  286. }
Success #stdin #stdout 0s 3484KB
stdin
Standard input is empty
stdout
** begin of program **
Hoge() : 1
FooPtr(LPFOO)
-- test 1 --
ope = ThisPtr
hoge1: 1
empty: 1
-- test 2 --
FooPtr(ThisPtr)
hoge1: 1
hoge2: 1
-- test 3 --
FooPtr(ThisPtr)
hoge1: 1
hgoe3: 1
-- test 4 --
FooPtr(ThisPtr)
ope = LPFOO
hoge4: 1
~Hoge() : 1
-- test 5 --
Hoge() : 2
ope = LPFOO
hoge1: 2
-- test 6 --
Hoge method : 2
-- test 7 --
Hoge() : 3
FooPtr(LPFOO)
~Hoge() : 3
Hoge() : 4
FooPtr(LPFOO)
ope = ThisPtr
~Hoge() : 2
-- test 8 --
Hoge method : 4
-- test 9 --
FooPtr(ThisPtr)
Hoge() : 5
FooPtr(LPFOO)
f1 == hoge1
f2 != hoge1
~Hoge() : 5
-- test 10 --
Hoge() : 6
FooPtr(LPFOO)
ope = ThisPtr
~Hoge() : 4
** end of program **
~Hoge() : 6