|
|
|||
File indexing completed on 2025-12-16 09:40:54
0001 // Copyright 2017 The Abseil Authors. 0002 // 0003 // Licensed under the Apache License, Version 2.0 (the "License"); 0004 // you may not use this file except in compliance with the License. 0005 // You may obtain a copy of the License at 0006 // 0007 // https://www.apache.org/licenses/LICENSE-2.0 0008 // 0009 // Unless required by applicable law or agreed to in writing, software 0010 // distributed under the License is distributed on an "AS IS" BASIS, 0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0012 // See the License for the specific language governing permissions and 0013 // limitations under the License. 0014 // 0015 // ----------------------------------------------------------------------------- 0016 // File: memory.h 0017 // ----------------------------------------------------------------------------- 0018 // 0019 // This header file contains utility functions for managing the creation and 0020 // conversion of smart pointers. This file is an extension to the C++ 0021 // standard <memory> library header file. 0022 0023 #ifndef ABSL_MEMORY_MEMORY_H_ 0024 #define ABSL_MEMORY_MEMORY_H_ 0025 0026 #include <cstddef> 0027 #include <limits> 0028 #include <memory> 0029 #include <new> 0030 #include <type_traits> 0031 #include <utility> 0032 0033 #include "absl/base/macros.h" 0034 #include "absl/meta/type_traits.h" 0035 0036 namespace absl { 0037 ABSL_NAMESPACE_BEGIN 0038 0039 // ----------------------------------------------------------------------------- 0040 // Function Template: WrapUnique() 0041 // ----------------------------------------------------------------------------- 0042 // 0043 // Adopts ownership from a raw pointer and transfers it to the returned 0044 // `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not* 0045 // specify the template type `T` when calling `WrapUnique`. 0046 // 0047 // Example: 0048 // X* NewX(int, int); 0049 // auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>. 0050 // 0051 // Do not call WrapUnique with an explicit type, as in 0052 // `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically 0053 // deduce the pointer type. If you wish to make the type explicit, just use 0054 // `std::unique_ptr` directly. 0055 // 0056 // auto x = std::unique_ptr<X>(NewX(1, 2)); 0057 // - or - 0058 // std::unique_ptr<X> x(NewX(1, 2)); 0059 // 0060 // While `absl::WrapUnique` is useful for capturing the output of a raw 0061 // pointer factory, prefer 'absl::make_unique<T>(args...)' over 0062 // 'absl::WrapUnique(new T(args...))'. 0063 // 0064 // auto x = WrapUnique(new X(1, 2)); // works, but nonideal. 0065 // auto x = make_unique<X>(1, 2); // safer, standard, avoids raw 'new'. 0066 // 0067 // Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid 0068 // expression. In particular, `absl::WrapUnique()` cannot wrap pointers to 0069 // arrays, functions or void, and it must not be used to capture pointers 0070 // obtained from array-new expressions (even though that would compile!). 0071 template <typename T> 0072 std::unique_ptr<T> WrapUnique(T* ptr) { 0073 static_assert(!std::is_array<T>::value, "array types are unsupported"); 0074 static_assert(std::is_object<T>::value, "non-object types are unsupported"); 0075 return std::unique_ptr<T>(ptr); 0076 } 0077 0078 // ----------------------------------------------------------------------------- 0079 // Function Template: make_unique<T>() 0080 // ----------------------------------------------------------------------------- 0081 // 0082 // Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries 0083 // during the construction process. `absl::make_unique<>` also avoids redundant 0084 // type declarations, by avoiding the need to explicitly use the `new` operator. 0085 // 0086 // https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique 0087 // 0088 // For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic, 0089 // see Herb Sutter's explanation on 0090 // (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/]. 0091 // (In general, reviewers should treat `new T(a,b)` with scrutiny.) 0092 // 0093 // Historical note: Abseil once provided a C++11 compatible implementation of 0094 // the C++14's `std::make_unique`. Now that C++11 support has been sunsetted, 0095 // `absl::make_unique` simply uses the STL-provided implementation. New code 0096 // should use `std::make_unique`. 0097 using std::make_unique; 0098 0099 // ----------------------------------------------------------------------------- 0100 // Function Template: RawPtr() 0101 // ----------------------------------------------------------------------------- 0102 // 0103 // Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is 0104 // useful within templates that need to handle a complement of raw pointers, 0105 // `std::nullptr_t`, and smart pointers. 0106 template <typename T> 0107 auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) { 0108 // ptr is a forwarding reference to support Ts with non-const operators. 0109 return (ptr != nullptr) ? std::addressof(*ptr) : nullptr; 0110 } 0111 inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; } 0112 0113 // ----------------------------------------------------------------------------- 0114 // Function Template: ShareUniquePtr() 0115 // ----------------------------------------------------------------------------- 0116 // 0117 // Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced 0118 // type. Ownership (if any) of the held value is transferred to the returned 0119 // shared pointer. 0120 // 0121 // Example: 0122 // 0123 // auto up = absl::make_unique<int>(10); 0124 // auto sp = absl::ShareUniquePtr(std::move(up)); // shared_ptr<int> 0125 // CHECK_EQ(*sp, 10); 0126 // CHECK(up == nullptr); 0127 // 0128 // Note that this conversion is correct even when T is an array type, and more 0129 // generally it works for *any* deleter of the `unique_ptr` (single-object 0130 // deleter, array deleter, or any custom deleter), since the deleter is adopted 0131 // by the shared pointer as well. The deleter is copied (unless it is a 0132 // reference). 0133 // 0134 // Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a 0135 // null shared pointer does not attempt to call the deleter. 0136 template <typename T, typename D> 0137 std::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) { 0138 return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>(); 0139 } 0140 0141 // ----------------------------------------------------------------------------- 0142 // Function Template: WeakenPtr() 0143 // ----------------------------------------------------------------------------- 0144 // 0145 // Creates a weak pointer associated with a given shared pointer. The returned 0146 // value is a `std::weak_ptr` of deduced type. 0147 // 0148 // Example: 0149 // 0150 // auto sp = std::make_shared<int>(10); 0151 // auto wp = absl::WeakenPtr(sp); 0152 // CHECK_EQ(sp.get(), wp.lock().get()); 0153 // sp.reset(); 0154 // CHECK(wp.lock() == nullptr); 0155 // 0156 template <typename T> 0157 std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) { 0158 return std::weak_ptr<T>(ptr); 0159 } 0160 0161 // ----------------------------------------------------------------------------- 0162 // Class Template: pointer_traits 0163 // ----------------------------------------------------------------------------- 0164 // 0165 // Historical note: Abseil once provided an implementation of 0166 // `std::pointer_traits` for platforms that had not yet provided it. Those 0167 // platforms are no longer supported. New code should simply use 0168 // `std::pointer_traits`. 0169 using std::pointer_traits; 0170 0171 // ----------------------------------------------------------------------------- 0172 // Class Template: allocator_traits 0173 // ----------------------------------------------------------------------------- 0174 // 0175 // Historical note: Abseil once provided an implementation of 0176 // `std::allocator_traits` for platforms that had not yet provided it. Those 0177 // platforms are no longer supported. New code should simply use 0178 // `std::allocator_traits`. 0179 using std::allocator_traits; 0180 0181 namespace memory_internal { 0182 0183 // ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D. 0184 template <template <typename> class Extract, typename Obj, typename Default, 0185 typename> 0186 struct ExtractOr { 0187 using type = Default; 0188 }; 0189 0190 template <template <typename> class Extract, typename Obj, typename Default> 0191 struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> { 0192 using type = Extract<Obj>; 0193 }; 0194 0195 template <template <typename> class Extract, typename Obj, typename Default> 0196 using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type; 0197 0198 // This template alias transforms Alloc::is_nothrow into a metafunction with 0199 // Alloc as a parameter so it can be used with ExtractOrT<>. 0200 template <typename Alloc> 0201 using GetIsNothrow = typename Alloc::is_nothrow; 0202 0203 } // namespace memory_internal 0204 0205 // ABSL_ALLOCATOR_NOTHROW is a build time configuration macro for user to 0206 // specify whether the default allocation function can throw or never throws. 0207 // If the allocation function never throws, user should define it to a non-zero 0208 // value (e.g. via `-DABSL_ALLOCATOR_NOTHROW`). 0209 // If the allocation function can throw, user should leave it undefined or 0210 // define it to zero. 0211 // 0212 // allocator_is_nothrow<Alloc> is a traits class that derives from 0213 // Alloc::is_nothrow if present, otherwise std::false_type. It's specialized 0214 // for Alloc = std::allocator<T> for any type T according to the state of 0215 // ABSL_ALLOCATOR_NOTHROW. 0216 // 0217 // default_allocator_is_nothrow is a class that derives from std::true_type 0218 // when the default allocator (global operator new) never throws, and 0219 // std::false_type when it can throw. It is a convenience shorthand for writing 0220 // allocator_is_nothrow<std::allocator<T>> (T can be any type). 0221 // NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from 0222 // the same type for all T, because users should specialize neither 0223 // allocator_is_nothrow nor std::allocator. 0224 template <typename Alloc> 0225 struct allocator_is_nothrow 0226 : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc, 0227 std::false_type> {}; 0228 0229 #if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW 0230 template <typename T> 0231 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {}; 0232 struct default_allocator_is_nothrow : std::true_type {}; 0233 #else 0234 struct default_allocator_is_nothrow : std::false_type {}; 0235 #endif 0236 0237 namespace memory_internal { 0238 template <typename Allocator, typename Iterator, typename... Args> 0239 void ConstructRange(Allocator& alloc, Iterator first, Iterator last, 0240 const Args&... args) { 0241 for (Iterator cur = first; cur != last; ++cur) { 0242 ABSL_INTERNAL_TRY { 0243 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), 0244 args...); 0245 } 0246 ABSL_INTERNAL_CATCH_ANY { 0247 while (cur != first) { 0248 --cur; 0249 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); 0250 } 0251 ABSL_INTERNAL_RETHROW; 0252 } 0253 } 0254 } 0255 0256 template <typename Allocator, typename Iterator, typename InputIterator> 0257 void CopyRange(Allocator& alloc, Iterator destination, InputIterator first, 0258 InputIterator last) { 0259 for (Iterator cur = destination; first != last; 0260 static_cast<void>(++cur), static_cast<void>(++first)) { 0261 ABSL_INTERNAL_TRY { 0262 std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur), 0263 *first); 0264 } 0265 ABSL_INTERNAL_CATCH_ANY { 0266 while (cur != destination) { 0267 --cur; 0268 std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur)); 0269 } 0270 ABSL_INTERNAL_RETHROW; 0271 } 0272 } 0273 } 0274 } // namespace memory_internal 0275 ABSL_NAMESPACE_END 0276 } // namespace absl 0277 0278 #endif // ABSL_MEMORY_MEMORY_H_
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|