Pigweed
Loading...
Searching...
No Matches
unique_ptr.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <memory>
17#include <utility>
18
19namespace pw {
20
21// Forward declaration.
22class Deallocator;
23
24namespace allocator::internal {
25
31 protected:
32 using Capability = ::pw::allocator::Capability;
33
34 static bool HasCapability(Deallocator* deallocator, Capability capability);
35 static void Deallocate(Deallocator* deallocator, void* ptr);
36};
37
38} // namespace allocator::internal
39
46template <typename T>
48 public:
50
55 constexpr UniquePtr() : value_(nullptr), deallocator_(nullptr) {}
56
61 constexpr UniquePtr(std::nullptr_t) : UniquePtr() {}
62
68 template <typename U>
69 UniquePtr(UniquePtr<U>&& other) noexcept
70 : value_(other.value_), deallocator_(other.deallocator_) {
71 static_assert(
72 std::is_assignable_v<T*&, U*>,
73 "Attempted to construct a UniquePtr<T> from a UniquePtr<U> where "
74 "U* is not assignable to T*.");
75 other.Release();
76 }
77
78 // Move-only. These are needed since the templated move-contructor and
79 // move-assignment operator do not exactly match the signature of the default
80 // move-contructor and move-assignment operator, and thus do not implicitly
81 // delete the copy-contructor and copy-assignment operator.
82 UniquePtr(const UniquePtr&) = delete;
83 UniquePtr& operator=(const UniquePtr&) = delete;
84
93 template <typename U>
94 UniquePtr& operator=(UniquePtr<U>&& other) noexcept {
95 static_assert(std::is_assignable_v<T*&, U*>,
96 "Attempted to assign a UniquePtr<U> to a UniquePtr<T> where "
97 "U* is not assignable to T*.");
98 Reset();
99 value_ = other.value_;
100 deallocator_ = other.deallocator_;
101 other.Release();
102 return *this;
103 }
104
110 UniquePtr& operator=(std::nullptr_t) {
111 Reset();
112 return *this;
113 }
114
117
119 Deallocator* deallocator() const { return deallocator_; }
120
125 T* Release() {
126 T* value = value_;
127 value_ = nullptr;
128 deallocator_ = nullptr;
129 return value;
130 }
131
136 void Reset() {
137 if (value_ == nullptr) {
138 return;
139 }
140 if (!Base::HasCapability(deallocator_, Capability::kSkipsDestroy)) {
141 std::destroy_at(value_);
142 }
143 Base::Deallocate(deallocator_, value_);
144 Release();
145 }
146
151 explicit operator bool() const = delete;
152
154 bool operator==(std::nullptr_t) const { return value_ == nullptr; }
155
158 bool operator!=(std::nullptr_t) const { return value_ != nullptr; }
159
161 T* get() { return value_; }
163 const T* get() const { return value_; }
164
169 T* operator->() { return value_; }
170 const T* operator->() const { return value_; }
171
176 T& operator*() { return *value_; }
177 const T& operator*() const { return *value_; }
178
179 private:
181 T* value_;
182
185 Deallocator* deallocator_;
186
192 template <typename U>
193 friend class UniquePtr;
194
195 class PrivateConstructorType {};
196 static constexpr PrivateConstructorType kPrivateConstructor{};
197
198 public:
206 UniquePtr(PrivateConstructorType, T* value, Deallocator* deallocator)
207 : value_(value), deallocator_(deallocator) {}
208
209 // Allow construction with ``kPrivateConstructor`` to the implementation
210 // of ``MakeUnique``.
211 friend class Deallocator;
212};
213
214namespace allocator {
215
216// Alias for module consumers using the older name for the above type.
217template <typename T>
219
220} // namespace allocator
221} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:26
Definition: unique_ptr.h:47
bool operator==(std::nullptr_t) const
Returns whether this UniquePtr is in an "empty" (nullptr) state.
Definition: unique_ptr.h:154
UniquePtr(UniquePtr< U > &&other) noexcept
Definition: unique_ptr.h:69
friend class UniquePtr
Definition: unique_ptr.h:193
bool operator!=(std::nullptr_t) const
Definition: unique_ptr.h:158
constexpr UniquePtr()
Definition: unique_ptr.h:55
T * get()
Returns the underlying (possibly null) pointer.
Definition: unique_ptr.h:161
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:119
constexpr UniquePtr(std::nullptr_t)
Definition: unique_ptr.h:61
UniquePtr & operator=(std::nullptr_t)
Definition: unique_ptr.h:110
void Reset()
Definition: unique_ptr.h:136
UniquePtr & operator=(UniquePtr< U > &&other) noexcept
Definition: unique_ptr.h:94
const T * get() const
Returns the underlying (possibly null) pointer.
Definition: unique_ptr.h:163
T * operator->()
Definition: unique_ptr.h:169
T & operator*()
Definition: unique_ptr.h:176
friend class Deallocator
TODO(b/326509341): Remove when downstream consumers migrate.
Definition: unique_ptr.h:211
UniquePtr(PrivateConstructorType, T *value, Deallocator *deallocator)
Definition: unique_ptr.h:206
~UniquePtr()
Destructs and deallocates any currently-held value.
Definition: unique_ptr.h:116
T * Release()
Definition: unique_ptr.h:125
Definition: unique_ptr.h:30
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27