#ifndef __R_H__ #define __R_H__ #include #include "primitive.h" #include "assert.h" #include #include class NullReference : public std::exception { public: virtual const char* what() const throw() override { return "Trying to use null reference"; } }; /* * Ahhoz hogy önhívatkozás működjön egyelőre egy hash_map-et * használjuk, későbbiékben majd vmi jobb megoldás, mert nagyon nem * teccik ez :) */ /*class RBase { public: typedef std::unordered_map map; inline RBase() { } inline void init() { instances.insert(map::value_type(ptr(), 0)); } virtual ~RBase() { instances.erase(ptr()); } inline bool isInitialized() const { return instances.end() != instances.find(ptr()); }; private: inline map::key_type ptr() const { return static_cast(this); }; static map instances; }; RBase::map RBase::instances;*/ template class R //: public RBase { public: // TODO: make protected struct VS // Value Structure { Int c; T* pVal; VS(Int c) : c(c) { } }; protected: /*R* stub; inline bool isStub() { }*/ // ctor explicit R(int i) : vs(new VS(1)) { // init(); } // ctor (lvalue) template R(R& o, int i) { vs = reinterpret_cast::VS*>(o.vs); cinc(); } // ctor (rvalue) template R(R&& o, int i) { vs = reinterpret_cast::VS*>(o.vs); cinc(); } public: // element type typedef T etype; // def ctor R() : vs(nullptr) { // init(); } // ctor template R(R& o) { _assert_subclass ERROR; vs = reinterpret_cast::VS*>(o.vs); cinc(); } template R(R&& o) { _assert_subclass ERROR; vs = reinterpret_cast::VS*>(o.vs); cinc(); } // dtor virtual ~R() { free(); } template R& operator=(R&& o) { _assert_subclass ERROR; return copy(o); } template R& operator=(R& o) { _assert_subclass ERROR; return copy(o); } protected: template inline R& copy(R& o) { // forceInit(); if ((void*)&o != (void*)this) { free(); vs = reinterpret_cast::VS*>(o.vs); cinc(); } return *reinterpret_cast< R* >(this); } template inline R& copy(R&& o) { // forceInit(); if ((void*)&o != (void*)this) { free(); vs = reinterpret_cast::VS*>(o.vs); cinc(); } return *reinterpret_cast< R* >(this); } public: // freeing void free() { if (/*isInitialized() && */cdec() == 0) // TODO: Implement structural cycle freeing { delete vs->pVal; delete vs; } vs = nullptr; } // dereferencing inline T& deref() { ensure(); return *vs->pVal; } inline Int refCount() const { ensure(); return vs->c; } bool isNull() const { return vs == nullptr; } /*friend R mkR(Int i); template friend R mkR(); template friend R mkR(UFirst first); template friend R mkR(UFirst first, USecond second); template friend R mkR(UFirst first, USecond second, UThird third); template friend R mkR(UFirst first, USecond second, UThird third, UFourth fourth);*/ friend class Ref; // operators inline T* operator->() { return &this->deref(); } inline T& operator *() { return this->deref(); } private: /*inline void forceInit() { if (!isInitialized()) { RBase::init(); vs = nullptr; } }*/ inline void ensure() const { if (vs == nullptr) { throw NullReference(); } } inline Int cinc() { if (vs != nullptr) { return ++vs->c; } else { return -1; } } inline Int cdec() { if (vs != nullptr) { return --vs->c; } else { return -1; } } // private data public: // TODO: make private VS* vs; }; class Ref { public: template static R mk() { R ref(0); ref.vs->pVal = new T(); return ref; } template static R mk(TFirst first) { R ref(0); ref.vs->pVal = new T(first); return ref; } template static R mk(TFirst first, TSecond second) { R ref(0); ref.vs->pVal = new T(first, second); return ref; } template static R mk(TFirst first, TSecond second, TThird third) { R ref(0); ref.vs->pVal = new T(first, second, third); return ref; } template static R mk(TFirst first, TSecond second, TThird third, TFourth fourth) { R ref(0); ref.vs->pVal = new T(first, second, third, fourth); return ref; } static R mk(Int i) { R ref(0); ref.vs->pVal = new Int(i); return ref; } }; /**** specialize for base types ****/ template<> class R : public R { protected: inline R(int i) : R(i) { } public: inline R() : R() { } inline R(R& o) : R(o, 0) { } inline R(R&& o) : R(o, 0) { } // additional ctor inline R(bool val) : R(0) { vs->pVal = new bool(val); } R& operator=(R& o) { R::copy(o); return *this; } R& operator=(R&& o) { R::copy(o); return *this; } friend class Ref; }; #endif