Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 <cstddef>
17#include <type_traits>
18#include <utility>
19
20#include "pw_allocator/config.h"
21#include "pw_allocator/internal/managed_ptr.h"
22#include "pw_allocator/layout.h"
23#include "pw_preprocessor/compiler.h"
24
25namespace pw {
26
40template <typename T>
41class UniquePtr : public ::pw::allocator::internal::ManagedPtr<T> {
42 private:
43 using Base = ::pw::allocator::internal::ManagedPtr<T>;
44 using Empty = ::pw::allocator::internal::Empty;
45
46 public:
47 using pointer = typename Base::element_type*;
48 using element_type = typename Base::element_type;
49
54 constexpr UniquePtr() noexcept {
55 if constexpr (std::is_array_v<T>) {
56 size_ = 0;
57 }
58 }
59
64 constexpr UniquePtr(std::nullptr_t) noexcept : UniquePtr() {}
65
80 UniquePtr(element_type* value, Deallocator& deallocator)
81 : Base(value), deallocator_(&deallocator) {
82 static_assert(!allocator::internal::is_unbounded_array_v<T>,
83 "UniquePtr for unbounded array type must provide size");
84 if constexpr (allocator::internal::is_bounded_array_v<T>) {
85 size_ = std::extent_v<T>;
86 }
87 }
88
89 UniquePtr(element_type* value, size_t size, Deallocator& deallocator)
90 : Base(value), size_(size), deallocator_(&deallocator) {
91 static_assert(
92 allocator::internal::is_unbounded_array_v<T>,
93 "UniquePtr must not provide size unless type is an unbounded array");
94 }
96
102 template <typename U>
103 UniquePtr(UniquePtr<U>&& other) noexcept {
104 *this = std::move(other);
105 }
106
109
116 template <typename U>
117 UniquePtr& operator=(UniquePtr<U>&& other) noexcept;
118
123 UniquePtr& operator=(std::nullptr_t) noexcept;
124
128 size_t size() const {
129 static_assert(std::is_array_v<T>,
130 "size() cannot be called with a non-array type");
131 return size_;
132 }
133
135 Deallocator* deallocator() const { return deallocator_; }
136
141 element_type* Release() noexcept;
142
147 void Reset() noexcept;
148
150 void Swap(UniquePtr& other);
151
152 private:
153 // Allow construction with to the implementation of `MakeUnique`.
154 friend class Deallocator;
155
156 // Allow UniquePtr<T> to access UniquePtr<U> and vice versa.
157 template <typename>
158 friend class UniquePtr;
159
161 template <typename U>
162 void CopyFrom(const UniquePtr<U>& other);
163
167 PW_NO_UNIQUE_ADDRESS
168 std::conditional_t<std::is_array_v<T>, size_t, Empty> size_;
169
172 Deallocator* deallocator_ = nullptr;
173};
174
175namespace allocator {
176
177// Alias for module consumers using the older name for the above type.
178template <typename T>
179using UniquePtr = PW_ALLOCATOR_DEPRECATED ::pw::UniquePtr<T>;
180
181} // namespace allocator
182
183// Template method implementations.
184
185template <typename T>
186template <typename U>
188 Reset();
189 CopyFrom(other);
190 other.Release();
191 return *this;
192}
193
194template <typename T>
195UniquePtr<T>& UniquePtr<T>::operator=(std::nullptr_t) noexcept {
196 Reset();
197 return *this;
198}
199
200template <typename T>
201typename UniquePtr<T>::element_type* UniquePtr<T>::Release() noexcept {
202 element_type* value = Base::Release();
203 deallocator_ = nullptr;
204 return value;
205}
206
207template <typename T>
208void UniquePtr<T>::Reset() noexcept {
209 if (*this == nullptr) {
210 return;
211 }
212 if (!Base::HasCapability(deallocator_, allocator::kSkipsDestroy)) {
213 if constexpr (std::is_array_v<T>) {
214 Base::Destroy(size_);
215 } else {
216 Base::Destroy();
217 }
218 }
219 Deallocator* deallocator = deallocator_;
220 auto* ptr = const_cast<std::remove_const_t<element_type>*>(Release());
221 Base::Deallocate(deallocator, ptr);
222}
223
224template <typename T>
226 Base::Swap(other);
227 if constexpr (std::is_array_v<T>) {
228 std::swap(size_, other.size_);
229 }
230 std::swap(deallocator_, other.deallocator_);
231}
232
233template <typename T>
234template <typename U>
235void UniquePtr<T>::CopyFrom(const UniquePtr<U>& other) {
236 static_assert(std::is_array_v<T> == std::is_array_v<U>);
237 Base::CopyFrom(other);
238 if constexpr (std::is_array_v<T>) {
239 size_ = other.size_;
240 }
241 deallocator_ = other.deallocator_;
242}
243
244} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:27
Definition: unique_ptr.h:41
UniquePtr(UniquePtr< U > &&other) noexcept
Definition: unique_ptr.h:103
element_type * Release() noexcept
Definition: unique_ptr.h:201
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:135
void Reset() noexcept
Definition: unique_ptr.h:208
UniquePtr(element_type *value, Deallocator &deallocator)
Definition: unique_ptr.h:80
constexpr UniquePtr() noexcept
Definition: unique_ptr.h:54
size_t size() const
Definition: unique_ptr.h:128
UniquePtr & operator=(UniquePtr< U > &&other) noexcept
~UniquePtr()
Frees any currently-held value.
Definition: unique_ptr.h:108
constexpr UniquePtr(std::nullptr_t) noexcept
Definition: unique_ptr.h:64
void Swap(UniquePtr &other)
Swaps the managed pointer and deallocator of this and another object.
Definition: unique_ptr.h:225
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27