memory.h (11324B)
1 // Copyright 2017 The Abseil Authors. 2 // 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 // 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, 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 // File: memory.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This header file contains utility functions for managing the creation and 20 // conversion of smart pointers. This file is an extension to the C++ 21 // standard <memory> library header file. 22 23 #ifndef ABSL_MEMORY_MEMORY_H_ 24 #define ABSL_MEMORY_MEMORY_H_ 25 26 #include <cstddef> 27 #include <limits> 28 #include <memory> 29 #include <new> 30 #include <type_traits> 31 #include <utility> 32 33 #include "absl/base/macros.h" 34 #include "absl/meta/type_traits.h" 35 36 namespace absl { 37 ABSL_NAMESPACE_BEGIN 38 39 // ----------------------------------------------------------------------------- 40 // Function Template: WrapUnique() 41 // ----------------------------------------------------------------------------- 42 // 43 // Adopts ownership from a raw pointer and transfers it to the returned 44 // `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not* 45 // specify the template type `T` when calling `WrapUnique`. 46 // 47 // Example: 48 // X* NewX(int, int); 49 // auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>. 50 // 51 // Do not call WrapUnique with an explicit type, as in 52 // `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically 53 // deduce the pointer type. If you wish to make the type explicit, just use 54 // `std::unique_ptr` directly. 55 // 56 // auto x = std::unique_ptr<X>(NewX(1, 2)); 57 // - or - 58 // std::unique_ptr<X> x(NewX(1, 2)); 59 // 60 // While `absl::WrapUnique` is useful for capturing the output of a raw 61 // pointer factory, prefer 'absl::make_unique<T>(args...)' over 62 // 'absl::WrapUnique(new T(args...))'. 63 // 64 // auto x = WrapUnique(new X(1, 2)); // works, but nonideal. 65 // auto x = make_unique<X>(1, 2); // safer, standard, avoids raw 'new'. 66 // 67 // Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid 68 // expression. In particular, `absl::WrapUnique()` cannot wrap pointers to 69 // arrays, functions or void, and it must not be used to capture pointers 70 // obtained from array-new expressions (even though that would compile!). 71 template <typename T> 72 std::unique_ptr<T> WrapUnique(T* ptr) { 73 static_assert(!std::is_array<T>::value, "array types are unsupported"); 74 static_assert(std::is_object<T>::value, "non-object types are unsupported"); 75 return std::unique_ptr<T>(ptr); 76 } 77 78 // ----------------------------------------------------------------------------- 79 // Function Template: make_unique<T>() 80 // ----------------------------------------------------------------------------- 81 // 82 // Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries 83 // during the construction process. `absl::make_unique<>` also avoids redundant 84 // type declarations, by avoiding the need to explicitly use the `new` operator. 85 // 86 // https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique 87 // 88 // For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic, 89 // see Herb Sutter's explanation on 90 // (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/]. 91 // (In general, reviewers should treat `new T(a,b)` with scrutiny.) 92 // 93 // Historical note: Abseil once provided a C++11 compatible implementation of 94 // the C++14's `std::make_unique`. Now that C++11 support has been sunsetted, 95 // `absl::make_unique` simply uses the STL-provided implementation. New code 96 // should use `std::make_unique`. 97 using std::make_unique; 98 99 // ----------------------------------------------------------------------------- 100 // Function Template: RawPtr() 101 // ----------------------------------------------------------------------------- 102 // 103 // Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is 104 // useful within templates that need to handle a complement of raw pointers, 105 // `std::nullptr_t`, and smart pointers. 106 template <typename T> 107 auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) { 108 // ptr is a forwarding reference to support Ts with non-const operators. 109 return (ptr != nullptr) ? std::addressof(*ptr) : nullptr; 110 } 111 inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; } 112 113 // ----------------------------------------------------------------------------- 114 // Function Template: ShareUniquePtr() 115 // ----------------------------------------------------------------------------- 116 // 117 // Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced 118 // type. Ownership (if any) of the held value is transferred to the returned 119 // shared pointer. 120 // 121 // Example: 122 // 123 // auto up = absl::make_unique<int>(10); 124 // auto sp = absl::ShareUniquePtr(std::move(up)); // shared_ptr<int> 125 // CHECK_EQ(*sp, 10); 126 // CHECK(up == nullptr); 127 // 128 // Note that this conversion is correct even when T is an array type, and more 129 // generally it works for *any* deleter of the `unique_ptr` (single-object 130 // deleter, array deleter, or any custom deleter), since the deleter is adopted 131 // by the shared pointer as well. The deleter is copied (unless it is a 132 // reference). 133 // 134 // Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a 135 // null shared pointer does not attempt to call the deleter. 136 template <typename T, typename D> 137 std::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) { 138 return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>(); 139 } 140 141 // ----------------------------------------------------------------------------- 142 // Function Template: WeakenPtr() 143 // ----------------------------------------------------------------------------- 144 // 145 // Creates a weak pointer associated with a given shared pointer. The returned 146 // value is a `std::weak_ptr` of deduced type. 147 // 148 // Example: 149 // 150 // auto sp = std::make_shared<int>(10); 151 // auto wp = absl::WeakenPtr(sp); 152 // CHECK_EQ(sp.get(), wp.lock().get()); 153 // sp.reset(); 154 // CHECK(wp.lock() == nullptr); 155 // 156 template <typename T> 157 std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) { 158 return std::weak_ptr<T>(ptr); 159 } 160 161 // ----------------------------------------------------------------------------- 162 // Class Template: pointer_traits 163 // ----------------------------------------------------------------------------- 164 // 165 // Historical note: Abseil once provided an implementation of 166 // `std::pointer_traits` for platforms that had not yet provided it. Those 167 // platforms are no longer supported. New code should simply use 168 // `std::pointer_traits`. 169 using std::pointer_traits; 170 171 // ----------------------------------------------------------------------------- 172 // Class Template: allocator_traits 173 // ----------------------------------------------------------------------------- 174 // 175 // Historical note: Abseil once provided an implementation of 176 // `std::allocator_traits` for platforms that had not yet provided it. Those 177 // platforms are no longer supported. New code should simply use 178 // `std::allocator_traits`. 179 using std::allocator_traits; 180 181 namespace memory_internal { 182 183 // ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D. 184 template <template <typename> class Extract, typename Obj, typename Default, 185 typename> 186 struct ExtractOr { 187 using type = Default; 188 }; 189 190 template <template <typename> class Extract, typename Obj, typename Default> 191 struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> { 192 using type = Extract<Obj>; 193 }; 194 195 template <template <typename> class Extract, typename Obj, typename Default> 196 using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type; 197 198 // This template alias transforms Alloc::is_nothrow into a metafunction with 199 // Alloc as a parameter so it can be used with ExtractOrT<>. 200 template <typename Alloc> 201 using GetIsNothrow = typename Alloc::is_nothrow; 202 203 } // namespace memory_internal 204 205 // ABSL_ALLOCATOR_NOTHROW is a build time configuration macro for user to 206 // specify whether the default allocation function can throw or never throws. 207 // If the allocation function never throws, user should define it to a non-zero 208 // value (e.g. via `-DABSL_ALLOCATOR_NOTHROW`). 209 // If the allocation function can throw, user should leave it undefined or 210 // define it to zero. 211 // 212 // allocator_is_nothrow<Alloc> is a traits class that derives from 213 // Alloc::is_nothrow if present, otherwise std::false_type. It's specialized 214 // for Alloc = std::allocator<T> for any type T according to the state of 215 // ABSL_ALLOCATOR_NOTHROW. 216 // 217 // default_allocator_is_nothrow is a class that derives from std::true_type 218 // when the default allocator (global operator new) never throws, and 219 // std::false_type when it can throw. It is a convenience shorthand for writing 220 // allocator_is_nothrow<std::allocator<T>> (T can be any type). 221 // NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from 222 // the same type for all T, because users should specialize neither 223 // allocator_is_nothrow nor std::allocator. 224 template <typename Alloc> 225 struct allocator_is_nothrow 226 : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc, 227 std::false_type> {}; 228 229 #if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW 230 template <typename T> 231 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {}; 232 struct default_allocator_is_nothrow : std::true_type {}; 233 #else 234 struct default_allocator_is_nothrow : std::false_type {}; 235 #endif 236 237 namespace memory_internal { 238 template <typename Allocator, typename Iterator, typename... Args> 239 void ConstructRange(Allocator& alloc, Iterator first, Iterator last, 240 const Args&... args) { 241 for (Iterator cur = first; cur != last; ++cur) { 242 ABSL_INTERNAL_TRY { 243 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), 244 args...); 245 } 246 ABSL_INTERNAL_CATCH_ANY { 247 while (cur != first) { 248 --cur; 249 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); 250 } 251 ABSL_INTERNAL_RETHROW; 252 } 253 } 254 } 255 256 template <typename Allocator, typename Iterator, typename InputIterator> 257 void CopyRange(Allocator& alloc, Iterator destination, InputIterator first, 258 InputIterator last) { 259 for (Iterator cur = destination; first != last; 260 static_cast<void>(++cur), static_cast<void>(++first)) { 261 ABSL_INTERNAL_TRY { 262 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), 263 *first); 264 } 265 ABSL_INTERNAL_CATCH_ANY { 266 while (cur != destination) { 267 --cur; 268 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); 269 } 270 ABSL_INTERNAL_RETHROW; 271 } 272 } 273 } 274 } // namespace memory_internal 275 ABSL_NAMESPACE_END 276 } // namespace absl 277 278 #endif // ABSL_MEMORY_MEMORY_H_