#pragma once #include #include #include namespace nix { /* A simple non-nullable reference-counted pointer. Actually a wrapper around std::shared_ptr that prevents non-null constructions. */ template class ref { private: std::shared_ptr p; public: ref(const ref & r) : p(r.p) { } explicit ref(const std::shared_ptr & p) : p(p) { if (!p) throw std::invalid_argument("null pointer cast to ref"); } explicit ref(T * p) : p(p) { if (!p) throw std::invalid_argument("null pointer cast to ref"); } T* operator ->() const { return &*p; } T& operator *() const { return *p; } operator std::shared_ptr () const { return p; } std::shared_ptr get_ptr() const { return p; } template ref cast() const { return ref(std::dynamic_pointer_cast(p)); } template std::shared_ptr dynamic_pointer_cast() const { return std::dynamic_pointer_cast(p); } template operator ref () const { return ref((std::shared_ptr) p); } private: template friend ref make_ref(Args&&... args); }; template inline ref make_ref(Args&&... args) { auto p = std::make_shared(std::forward(args)...); return ref(p); } }