| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FBL_UNIQUE_FREE_PTR_H_ |
| #define FBL_UNIQUE_FREE_PTR_H_ |
| |
| #include <stdlib.h> |
| #include <fbl/macros.h> |
| |
| namespace fbl { |
| |
| // This is exactly like unique_ptr except that it deallocates using free() instead of delete. |
| // This should only be used on types without destructors, like 'char' or C structs. |
| template <typename T> |
| class unique_free_ptr { |
| public: |
| static_assert(std::is_trivially_destructible_v<T>, "unique_free_ptr can only be used on types with trivial destructors"); |
| |
| constexpr unique_free_ptr() : ptr_(nullptr) {} |
| constexpr unique_free_ptr(decltype(nullptr)) : unique_free_ptr() {} |
| |
| explicit unique_free_ptr(T* t) : ptr_(t) { } |
| |
| ~unique_free_ptr() { |
| free(ptr_); |
| } |
| |
| unique_free_ptr(unique_free_ptr&& o) : ptr_(o.release()) {} |
| unique_free_ptr& operator=(unique_free_ptr&& o) { |
| reset(o.release()); |
| return *this; |
| } |
| |
| unique_free_ptr& operator=(decltype(nullptr)) { |
| reset(); |
| return *this; |
| } |
| |
| // Comparison against nullptr operators (of the form, myptr == nullptr). |
| bool operator==(decltype(nullptr)) const { return (ptr_ == nullptr); } |
| bool operator!=(decltype(nullptr)) const { return (ptr_ != nullptr); } |
| |
| // Comparison against other unique_free_ptr<>'s. |
| bool operator==(const unique_free_ptr& o) const { return ptr_ == o.ptr_; } |
| bool operator!=(const unique_free_ptr& o) const { return ptr_ != o.ptr_; } |
| bool operator< (const unique_free_ptr& o) const { return ptr_ < o.ptr_; } |
| bool operator<=(const unique_free_ptr& o) const { return ptr_ <= o.ptr_; } |
| bool operator> (const unique_free_ptr& o) const { return ptr_ > o.ptr_; } |
| bool operator>=(const unique_free_ptr& o) const { return ptr_ >= o.ptr_; } |
| |
| // move semantics only |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(unique_free_ptr); |
| |
| T* release() { |
| T* t = ptr_; |
| ptr_ = nullptr; |
| return t; |
| } |
| void reset(T* t = nullptr) { |
| free(ptr_); |
| ptr_ = t; |
| } |
| void swap(unique_free_ptr& other) { |
| T* t = ptr_; |
| ptr_ = other.ptr_; |
| other.ptr_ = t; |
| } |
| |
| T* get() const { |
| return ptr_; |
| } |
| |
| explicit operator bool() const { |
| return static_cast<bool>(ptr_); |
| } |
| |
| T& operator*() const { |
| return *ptr_; |
| } |
| T* operator->() const { |
| return ptr_; |
| } |
| |
| private: |
| T* ptr_; |
| }; |
| |
| // Comparison against nullptrs (of the form, nullptr == myptr) |
| template <typename T> |
| static inline bool operator==(decltype(nullptr), const unique_free_ptr<T>& ptr) { |
| return (ptr.get() == nullptr); |
| } |
| |
| template <typename T> |
| static inline bool operator!=(decltype(nullptr), const unique_free_ptr<T>& ptr) { |
| return (ptr.get() != nullptr); |
| } |
| |
| } // namespace fbl |
| |
| #endif // FBL_UNIQUE_FREE_PTR_H_ |