//======================================================================= // Copyright Baptiste Wicht 2013-2016. // Distributed under the terms of the MIT License. // (See accompanying file LICENSE or copy at // http://www.opensource.org/licenses/MIT) //======================================================================= #ifndef UNIQUE_PTR_H #define UNIQUE_PTR_H #include #include namespace std { template struct default_delete { constexpr default_delete() = default; constexpr default_delete(const default_delete&) {} void operator()(T* ptr) const { static_assert(sizeof(T) > 0, "Type must be complete"); delete ptr; } }; //Partial specialization for arrays template struct default_delete { constexpr default_delete() = default; constexpr default_delete(const default_delete&) {} void operator()(T* ptr) const { static_assert(sizeof(T) > 0, "Type must be complete"); delete[] ptr; } }; template > class unique_ptr { public: using pointer_type = T*; using element_type = T; using deleter_type = D; private: using data_impl = tuple; data_impl _data; public: unique_ptr() : _data() {} unique_ptr(decltype(nullptr)) : unique_ptr() {} explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {} unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {} unique_ptr& operator=(unique_ptr&& u){ reset(u.unlock()); get_deleter() = std::forward(u.get_deleter()); return *this; } ~unique_ptr(){ reset(); } // Disable copy unique_ptr(const unique_ptr& rhs) = delete; unique_ptr& operator=(const unique_ptr& rhs) = delete; unique_ptr& operator=(decltype(nullptr)){ reset(); return *this; } //Access element_type& operator*() const { return *get(); } pointer_type operator->() const { return get(); } pointer_type get() const { return std::get<0>(_data); } deleter_type& get_deleter(){ return std::get<1>(_data); } const deleter_type& get_deleter() const { return std::get<1>(_data); } explicit operator bool() const { return get() == pointer_type() ? false : true; } pointer_type unlock(){ pointer_type p = get(); std::get<0>(_data) = pointer_type(); return p; } void reset(pointer_type p = pointer_type()){ if(get() != pointer_type()){ get_deleter()(get()); } std::get<0>(_data) = p; } }; //Partial specialization for array template class unique_ptr { public: using pointer_type = T*; using element_type = T; using deleter_type = D; private: using data_impl = tuple; data_impl _data; public: unique_ptr() : _data() {} unique_ptr(decltype(nullptr)) : unique_ptr() {} explicit unique_ptr(pointer_type p) : _data(make_tuple(p, deleter_type())) {} unique_ptr(unique_ptr&& u) : _data(make_tuple(u.unlock(), u.get_deleter())) {} unique_ptr& operator=(unique_ptr&& u){ reset(u.unlock()); get_deleter() = std::forward(u.get_deleter()); return *this; } ~unique_ptr(){ reset(); } // Disable copy unique_ptr(const unique_ptr& rhs) = delete; unique_ptr& operator=(const unique_ptr& rhs) = delete; unique_ptr& operator=(decltype(nullptr)){ reset(); return *this; } pointer_type get() const { return std::get<0>(_data); } deleter_type& get_deleter(){ return std::get<1>(_data); } const deleter_type& get_deleter() const { return std::get<1>(_data); } element_type& operator[](size_t i) const { return get()[i]; } explicit operator bool() const { return get() == pointer_type() ? false : true; } pointer_type unlock(){ pointer_type p = get(); std::get<0>(_data) = pointer_type(); return p; } void reset(){ reset(pointer_type()); } void reset(pointer_type p){ auto tmp = get(); std::get<0>(_data) = p; if(tmp){ get_deleter()(tmp); } } }; static_assert(sizeof(unique_ptr) == sizeof(long), "unique_ptr must have zero overhead with default deleter"); static_assert(sizeof(unique_ptr) == sizeof(long), "unique_ptr must have zero overhead with default deleter"); template std::unique_ptr make_unique(Args&&... args){ return std::unique_ptr(new T(std::forward(args)...)); } } //end of namespace std #endif