#if !defined(CODEQL_MEMORY_H) #define CODEQL_MEMORY_H namespace std { namespace detail { template class compressed_pair_element { T element; public: compressed_pair_element() = default; compressed_pair_element(const T& t) : element(t) {} T& get() { return element; } const T& get() const { return element; } }; template struct compressed_pair : private compressed_pair_element, private compressed_pair_element { compressed_pair() = default; compressed_pair(T& t) : compressed_pair_element(t), compressed_pair_element() {} compressed_pair(const compressed_pair&) = delete; compressed_pair(compressed_pair&&) noexcept = default; T& first() { return static_cast&>(*this).get(); } U& second() { return static_cast&>(*this).get(); } const T& first() const { return static_cast&>(*this).get(); } const U& second() const { return static_cast&>(*this).get(); } }; } template struct default_delete { void operator()(T* ptr) const { delete ptr; } }; template struct default_delete { template void operator()(U* ptr) const { delete[] ptr; } }; template > class unique_ptr { private: detail::compressed_pair data; public: constexpr unique_ptr() noexcept {} explicit unique_ptr(T* ptr) noexcept : data(ptr) {} unique_ptr(const unique_ptr& ptr) = delete; unique_ptr(unique_ptr&& ptr) noexcept = default; unique_ptr& operator=(unique_ptr&& ptr) noexcept = default; T& operator*() const { return *get(); } T* operator->() const noexcept { return get(); } T* get() const noexcept { return data.first(); } T* release() noexcept { Deleter& d = data.second(); d(data.first()); data.first() = nullptr; } ~unique_ptr() { Deleter& d = data.second(); d(data.first()); } }; template unique_ptr make_unique(Args&&... args) { return unique_ptr(new T(args...)); // std::forward calls elided for simplicity. } class ctrl_block { unsigned uses; public: ctrl_block() : uses(1) {} void inc() { ++uses; } bool dec() { return --uses == 0; } virtual void destroy() = 0; virtual ~ctrl_block() {} }; template > struct ctrl_block_impl: public ctrl_block { T* ptr; Deleter d; ctrl_block_impl(T* ptr, Deleter d) : ptr(ptr), d(d) {} virtual void destroy() override { d(ptr); } }; template class shared_ptr { private: ctrl_block* ctrl; T* ptr; void dec() { if(ctrl->dec()) { ctrl->destroy(); delete ctrl; } } void inc() { ctrl->inc(); } public: constexpr shared_ptr() noexcept = default; shared_ptr(T* ptr) : ctrl(new ctrl_block_impl(ptr, default_delete())) {} shared_ptr(const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) { inc(); } shared_ptr(shared_ptr&& s) noexcept = default; shared_ptr(unique_ptr&& s) : shared_ptr(s.release()) { } T* operator->() const { return ptr; } T& operator*() const { return *ptr; } T* get() const noexcept { return ptr; } ~shared_ptr() { dec(); } }; template shared_ptr make_shared(Args&&... args) { return shared_ptr(new T(args...)); // std::forward calls elided for simplicity. } } #endif