#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 { // TODO(tazjin): rename to brainworm_ref or something 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); } } // namespace nix