1 /* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://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, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_BASE_CONTAINERS_UNIQUE_PTR_H 17 #define API_BASE_CONTAINERS_UNIQUE_PTR_H 18 19 #include <cstddef> 20 21 #include <base/containers/type_traits.h> 22 #include <base/namespace.h> 23 24 BASE_BEGIN_NAMESPACE() 25 template<class T> 26 struct default_delete { 27 constexpr default_delete() noexcept = default; 28 29 template<class U> default_deletedefault_delete30 default_delete(const default_delete<U>& d) noexcept 31 {} 32 operatordefault_delete33 void operator()(T* ptr) const 34 { 35 delete ptr; 36 } 37 38 template<class U> operatordefault_delete39 void operator()(U* ptr) const 40 { 41 delete ptr; 42 } 43 }; 44 45 template<class T> 46 struct default_delete<T[]> { 47 constexpr default_delete() noexcept = default; 48 49 template<class U> 50 default_delete(const default_delete<U[]>& d) noexcept 51 {} 52 53 void operator()(T* ptr) const 54 { 55 delete[] ptr; 56 } 57 58 template<class U> 59 void operator()(U* ptr) const 60 { 61 delete[] ptr; 62 } 63 }; 64 65 template<class T, class D = default_delete<T>> 66 class unique_ptr { 67 public: 68 using pointer = BASE_NS::remove_reference_t<T>*; 69 using element_type = T; 70 using deleter_type = D; 71 72 constexpr unique_ptr() noexcept {}; 73 74 constexpr unique_ptr(nullptr_t) noexcept {} 75 76 explicit unique_ptr(pointer p) noexcept : ptr_(p) {} 77 78 // D is non-reference 79 template<class dt = D, enable_if_t<!is_reference_v<dt>, int> = 0> 80 unique_ptr(pointer p, const D& deleter) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 81 {} 82 template<class dt = D, enable_if_t<!is_reference_v<dt>, int> = 0> 83 unique_ptr(pointer p, BASE_NS::remove_reference_t<D>&& deleter) noexcept 84 : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 85 {} 86 87 // D is lvalue-reference "A&" 88 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 89 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && !BASE_NS::is_const_v<dt>), int> = 0> 90 unique_ptr(pointer p, D& deleter) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 91 {} 92 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 93 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && !BASE_NS::is_const_v<dt>), int> = 0> 94 unique_ptr(pointer p, BASE_NS::remove_reference_t<D>&& deleter) = delete; 95 96 // D is lvalue-reference "const A&" 97 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 98 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && BASE_NS::is_const_v<dt>), int> = 0> 99 unique_ptr(pointer p, const D& deleter) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 100 {} 101 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 102 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && BASE_NS::is_const_v<dt>), int> = 0> 103 unique_ptr(pointer p, const BASE_NS::remove_reference_t<D>&& deleter) = delete; 104 105 // if E is a reference type, this deleter is copy constructed from u's deleter 106 template<class U, class E, enable_if_t<!is_array_v<U> && is_reference_v<E>, int> = 0> 107 unique_ptr(unique_ptr<U, E>&& u) noexcept : ptr_(u.release()), deleter_(u.get_deleter()) 108 {} 109 110 // if E is a non-reference type, this D is move constructed from u's D 111 template<class U, class E, enable_if_t<!is_array_v<U> && !is_reference_v<E>, int> = 0> 112 unique_ptr(unique_ptr<U, E>&& u) noexcept : ptr_(u.release()), deleter_(BASE_NS::move(u.get_deleter())) 113 {} 114 115 ~unique_ptr() 116 { 117 if (ptr_) { 118 deleter_(ptr_); 119 } 120 } 121 122 deleter_type& get_deleter() noexcept 123 { 124 return deleter_; 125 } 126 const deleter_type& get_deleter() const noexcept 127 { 128 return deleter_; 129 } 130 131 pointer get() const noexcept 132 { 133 return ptr_; 134 } 135 136 pointer release() noexcept 137 { 138 pointer res = ptr_; 139 ptr_ = nullptr; 140 return res; 141 } 142 143 void reset(pointer ptr = pointer()) noexcept 144 { 145 pointer old_ptr = ptr_; 146 ptr_ = ptr; 147 if (old_ptr) { 148 deleter_(old_ptr); 149 } 150 } 151 152 unique_ptr& operator=(nullptr_t) noexcept 153 { 154 reset(); 155 return *this; 156 } 157 158 unique_ptr& operator=(unique_ptr&& r) noexcept 159 { 160 reset(r.release()); 161 deleter_ = r.get_deleter(); 162 return *this; 163 } 164 165 template<class U, class E> 166 unique_ptr& operator=(unique_ptr<U, E>&& r) noexcept 167 { 168 reset(r.release()); 169 deleter_ = r.get_deleter(); 170 return *this; 171 } 172 173 void swap(unique_ptr& other) noexcept 174 { 175 pointer tmp = ptr_; 176 ptr_ = other.ptr_; 177 other.ptr_ = tmp; 178 auto tmp2 = deleter_; 179 deleter_ = other.deleter_; 180 other.deleter_ = tmp2; 181 } 182 183 explicit operator bool() const noexcept 184 { 185 return (ptr_ != nullptr); 186 } 187 188 pointer operator->() const noexcept 189 { 190 return ptr_; 191 } 192 193 typename BASE_NS::add_lvalue_reference<T>::type operator*() const 194 { 195 return *ptr_; 196 } 197 198 unique_ptr(const unique_ptr&) = delete; 199 unique_ptr& operator=(const unique_ptr&) = delete; 200 201 protected: 202 pointer ptr_ { nullptr }; 203 D deleter_; 204 }; 205 206 template<class T, class D> 207 class unique_ptr<T[], D> { 208 public: 209 using pointer = BASE_NS::remove_reference_t<T>*; 210 using element_type = T; 211 using deleter_type = D; 212 213 constexpr unique_ptr() noexcept {} 214 215 constexpr unique_ptr(nullptr_t) noexcept {} 216 217 explicit unique_ptr(pointer p) noexcept : ptr_(p) {} 218 219 template<class U> 220 explicit unique_ptr(U p) noexcept : ptr_(p) 221 {} 222 223 // D is non-reference 224 template<class dt = D, enable_if_t<!is_reference_v<dt>, int> = 0> 225 unique_ptr(pointer p, const D& d) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(d)>(d)) 226 {} 227 template<class dt = D, enable_if_t<!is_reference_v<dt>, int> = 0> 228 unique_ptr(pointer p, BASE_NS::remove_reference_t<D>&& d) noexcept 229 : ptr_(p), deleter_(BASE_NS::forward<decltype(d)>(d)) 230 {} 231 232 // D is lvalue-reference "A&" 233 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 234 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && !BASE_NS::is_const_v<dt>), int> = 0> 235 unique_ptr(pointer p, D& deleter) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 236 {} 237 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 238 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && !BASE_NS::is_const_v<dt>), int> = 0> 239 unique_ptr(pointer p, BASE_NS::remove_reference_t<D>&& deleter) = delete; 240 241 // D is lvalue-reference "const A&" 242 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 243 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && BASE_NS::is_const_v<dt>), int> = 0> 244 unique_ptr(pointer p, const D& deleter) noexcept : ptr_(p), deleter_(BASE_NS::forward<decltype(deleter)>(deleter)) 245 {} 246 template<class d = D, class dt = BASE_NS::remove_reference_t<D>, 247 BASE_NS::enable_if_t<(BASE_NS::is_lvalue_reference_v<d> && BASE_NS::is_const_v<dt>), int> = 0> 248 unique_ptr(pointer p, const BASE_NS::remove_reference_t<D>&& deleter) = delete; 249 250 // if E is a reference type, this deleter is copy constructed from u's deleter 251 template<class U, class E, enable_if_t<is_array_v<U> && is_reference_v<E>, int> = 0> 252 unique_ptr(unique_ptr<U, E>&& u) noexcept : ptr_(u.release()), deleter_(u.get_deleter()) 253 {} 254 255 // if E is a non-reference type, this D is move constructed from u's D 256 template<class U, class E, enable_if_t<is_array_v<U> && !is_reference_v<E>, int> = 0> 257 unique_ptr(unique_ptr<U, E>&& u) noexcept : ptr_(u.release()), deleter_(BASE_NS::move(u.get_deleter())) 258 {} 259 260 ~unique_ptr() 261 { 262 if (ptr_) { 263 deleter_(ptr_); 264 } 265 } 266 267 deleter_type& get_deleter() noexcept 268 { 269 return deleter_; 270 } 271 272 const deleter_type& get_deleter() const noexcept 273 { 274 return deleter_; 275 } 276 277 pointer get() const noexcept 278 { 279 return ptr_; 280 } 281 282 pointer release() noexcept 283 { 284 pointer res = ptr_; 285 ptr_ = nullptr; 286 return res; 287 } 288 289 template<class U> 290 void reset(U ptr) noexcept 291 { 292 pointer old_ptr = ptr_; 293 ptr_ = ptr; 294 if (old_ptr) { 295 deleter_(old_ptr); 296 } 297 } 298 299 void reset(nullptr_t p = nullptr) noexcept 300 { 301 reset(pointer()); 302 } 303 304 unique_ptr& operator=(nullptr_t) noexcept 305 { 306 reset(); 307 return *this; 308 } 309 310 unique_ptr& operator=(unique_ptr&& r) noexcept 311 { 312 reset(r.release()); 313 deleter_ = r.get_deleter(); 314 return *this; 315 } 316 317 template<class U, class E> 318 319 unique_ptr& operator=(unique_ptr<U, E>&& r) noexcept 320 { 321 reset(r.release()); 322 deleter_ = r.get_deleter(); 323 return *this; 324 } 325 326 void swap(unique_ptr& other) noexcept 327 { 328 pointer tmp = ptr_; 329 ptr_ = other.ptr_; 330 other.ptr_ = tmp; 331 auto tmp2 = deleter_; 332 deleter_ = other.deleter_; 333 other.deleter_ = tmp2; 334 } 335 336 explicit operator bool() const noexcept 337 { 338 return (ptr_ != nullptr); 339 } 340 341 T& operator[](size_t i) const 342 { 343 return ptr_[i]; 344 } 345 346 unique_ptr(const unique_ptr&) = delete; 347 348 unique_ptr& operator=(const unique_ptr&) = delete; 349 350 protected: 351 pointer ptr_ { nullptr }; 352 D deleter_; 353 }; 354 355 // equality comparisons 356 template<class T1, class D1, class T2, class D2> 357 bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) 358 { 359 return x.get() == y.get(); 360 } 361 template<class T1, class D1> 362 bool operator==(const unique_ptr<T1, D1>& x, nullptr_t) 363 { 364 return x.get() == nullptr; 365 } 366 template<class T1, class D1> 367 bool operator==(nullptr_t, const unique_ptr<T1, D1>& x) 368 { 369 return x.get() == nullptr; 370 } 371 372 // in-equality comparisons 373 template<class T1, class D1, class T2, class D2> 374 bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) 375 { 376 return x.get() != y.get(); 377 } 378 template<class T1, class D1> 379 bool operator!=(const unique_ptr<T1, D1>& x, nullptr_t) 380 { 381 return x.get() != nullptr; 382 } 383 template<class T1, class D1> 384 bool operator!=(nullptr_t, const unique_ptr<T1, D1>& x) 385 { 386 return x.get() != nullptr; 387 } 388 389 // non-array types 390 template<class T, class... Args, BASE_NS::enable_if_t<!BASE_NS::is_array_v<T>, int> = 0> 391 unique_ptr<T> make_unique(Args&&... args) 392 { 393 return unique_ptr<T>(new T(BASE_NS::forward<Args>(args)...)); 394 } 395 396 // arrays with unknown bound 397 template<class T, BASE_NS::enable_if_t<BASE_NS::is_array_v<T> && BASE_NS::extent_v<T> == 0, int> = 0> 398 unique_ptr<T> make_unique(size_t size) 399 { 400 return unique_ptr<T>(new typename BASE_NS::remove_extent_t<T>[size]()); 401 } 402 403 // arrays with known bound. (not-allowed) 404 template<class T, class... Args, BASE_NS::enable_if_t<BASE_NS::is_array_v<T> && BASE_NS::extent_v<T> != 0, int> = 0> 405 void make_unique(Args&&... args) = delete; 406 BASE_END_NAMESPACE() 407 408 #endif // API_BASE_CONTAINERS_UNIQUE_PTR_H