#ifndef OBJECT_PROXY_HPP #define OBJECT_PROXY_HPP #include namespace matador::object { class basic_object_proxy { public: virtual ~basic_object_proxy() = default; [[nodiscard]] virtual void *get() const = 0; }; template < typename Type > class object_proxy; template < typename Type > class object_resolver { public: virtual ~object_resolver() = default; virtual Type* resolve(const object_proxy &proxy) const = 0; }; template < typename Type > class simple_object_resolver final : public object_resolver { public: simple_object_resolver() = default; explicit simple_object_resolver(Type* obj) : obj_(obj) {} explicit simple_object_resolver(std::unique_ptr obj) : obj_(std::move(obj)) {} Type* resolve(const object_proxy &/*proxy*/) const override { return obj_.get(); } private: std::unique_ptr obj_{}; }; template class object_proxy final : public basic_object_proxy { public: object_proxy() = default; explicit object_proxy(Type* obj) : resolver_(std::make_unique>(obj)) {} explicit object_proxy(std::unique_ptr obj) : resolver_(std::move(obj)) {} [[nodiscard]] void *get() const override { return static_cast(pointer()); } Type* operator->() const { return pointer(); } Type& operator*() { return *pointer(); } const Type& operator*() const { return *pointer(); } Type* pointer() const { return resolve(); } Type& ref() { return *pointer(); } const Type& ref() const { return *pointer(); } void reset(Type* obj) { resolver_ = std::make_unique>(obj); } void reset(std::unique_ptr obj) { resolver_ = std::make_unique>(std::move(obj)); } void reset(std::unique_ptr> &&resolver) { resolver_ = std::move(resolver); } private: Type* resolve() const { return resolver_->resolve(*this); } private: std::unique_ptr> resolver_{std::make_unique>()}; }; } #endif //OBJECT_PROXY_HPP