Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: base/memory/scoped_ptr.h

Issue 1454993003: Add a move constructor and move assignment operator to scoped_ptr. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add header Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Scopers help you manage ownership of a pointer, helping you easily manage a 5 // Scopers help you manage ownership of a pointer, helping you easily manage a
6 // pointer within a scope, and automatically destroying the pointer at the end 6 // pointer within a scope, and automatically destroying the pointer at the end
7 // of a scope. There are two main classes you will use, which correspond to the 7 // of a scope. There are two main classes you will use, which correspond to the
8 // operators new/delete and new[]/delete[]. 8 // operators new/delete and new[]/delete[].
9 // 9 //
10 // Example usage (scoped_ptr<T>): 10 // Example usage (scoped_ptr<T>):
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 79
80 // This is an implementation designed to match the anticipated future TR2 80 // This is an implementation designed to match the anticipated future TR2
81 // implementation of the scoped_ptr class. 81 // implementation of the scoped_ptr class.
82 82
83 #include <assert.h> 83 #include <assert.h>
84 #include <stddef.h> 84 #include <stddef.h>
85 #include <stdlib.h> 85 #include <stdlib.h>
86 86
87 #include <iosfwd> 87 #include <iosfwd>
88 #include <memory> 88 #include <memory>
89 #include <type_traits>
89 #include <utility> 90 #include <utility>
90 91
91 #include "base/basictypes.h" 92 #include "base/basictypes.h"
92 #include "base/compiler_specific.h" 93 #include "base/compiler_specific.h"
93 #include "base/move.h" 94 #include "base/move.h"
94 #include "base/template_util.h" 95 #include "base/template_util.h"
95 96
96 namespace base { 97 namespace base {
97 98
98 namespace subtle { 99 namespace subtle {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 252
252 // Constructor. Takes ownership of p. 253 // Constructor. Takes ownership of p.
253 explicit scoped_ptr(element_type* p) : impl_(p) {} 254 explicit scoped_ptr(element_type* p) : impl_(p) {}
254 255
255 // Constructor. Allows initialization of a stateful deleter. 256 // Constructor. Allows initialization of a stateful deleter.
256 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} 257 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
257 258
258 // Constructor. Allows construction from a nullptr. 259 // Constructor. Allows construction from a nullptr.
259 scoped_ptr(std::nullptr_t) : impl_(nullptr) {} 260 scoped_ptr(std::nullptr_t) : impl_(nullptr) {}
260 261
261 // Constructor. Allows construction from a scoped_ptr rvalue for a 262 // Move constructor.
263 //
264 // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and
265 // not just the conversion constructor) in order to warn on pessimizing moves.
266 // The requirements for the move constructor are specified in C++11
267 // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As
268 // we
vmpstr 2015/11/19 21:00:24 <_<
danakj 2015/11/19 21:03:36 wrapping broke
dcheng 2015/11/19 21:26:04 Oops.
269 // don't support reference (or move-only) deleters, the post conditions are
270 // trivially true: we always copy construct the deleter from other's deleter.
271 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
272
273 // Conversion constructor. Allows construction from a scoped_ptr rvalue for a
262 // convertible type and deleter. 274 // convertible type and deleter.
263 // 275 //
264 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct 276 // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only
265 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor 277 // participate in overload resolution if all the following are true:
266 // has different post-conditions if D is a reference type. Since this 278 // - U is implicitly convertible to T: this is important for 2 reasons:
267 // implementation does not support deleters with reference type, 279 // 1. So type traits don't incorrectly return true, e.g.
268 // we do not need a separate move constructor allowing us to avoid one 280 // std::is_convertible<scoped_ptr<Base>, scoped_ptr<Derived>>::value
269 // use of SFINAE. You only need to care about this if you modify the 281 // should be false.
270 // implementation of scoped_ptr. 282 // 2. To make sure code like this compiles:
271 template <typename U, typename V> 283 // void F(scoped_ptr<int>);
272 scoped_ptr(scoped_ptr<U, V>&& other) 284 // void F(scoped_ptr<Base>);
273 : impl_(&other.impl_) { 285 // // ambiguous since both conversion constructors match.
danakj 2015/11/19 21:03:36 nit: capital A
dcheng 2015/11/19 21:26:04 Done.
274 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); 286 // F(scoped_ptr<Derived>());
287 // - U is not an array type: to prevent conversions from scoped_ptr<T[]> to
288 // scoped_ptr<T>.
289 // - D is a reference type and E is the same type, or D is not a reference
290 // type and E is implicitly convertible to D: again, we don't support
291 // reference deleters, so we only worry about the latter requirement.
292 template <typename U,
293 typename E,
dcheng 2015/11/19 20:49:10 I renamed the second template parameter from V to
danakj 2015/11/19 21:03:36 sgtm
294 typename = typename std::enable_if<
295 !std::is_array<U>::value &&
296 std::is_convertible<typename scoped_ptr<U, E>::pointer_type,
297 pointer_type>::value &&
298 std::is_convertible<E, D>::value>::type>
299 scoped_ptr(scoped_ptr<U, E>&& other)
300 : impl_(&other.impl_) {}
301
302 // operator=.
303 //
304 // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to
305 // require a move assignment operator to trigger the pessimizing move warning:
306 // in this case, the warning triggers when moving a temporary. For consistency
307 // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3
308 // defines several requirements around this: like the move constructor, the
309 // requirements are simplified by the fact that we don't support move-only or
310 // reference deleters.
311 scoped_ptr& operator=(scoped_ptr&& rhs) {
312 impl_.TakeState(&rhs.impl_);
313 return *this;
275 } 314 }
276 315
277 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible 316 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
278 // type and deleter. 317 // type and deleter.
279 // 318 //
280 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from 319 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
281 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated 320 // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the
282 // form has different requirements on for move-only Deleters. Since this 321 // requirement for this operator, but like the conversion constructor, the
283 // implementation does not support move-only Deleters, we do not need a 322 // requirements are greatly simplified by not supporting move-only or
284 // separate move assignment operator allowing us to avoid one use of SFINAE. 323 // reference deleters.
285 // You only need to care about this if you modify the implementation of 324 template <typename U,
286 // scoped_ptr. 325 typename E,
287 template <typename U, typename V> 326 typename = typename std::enable_if<
vmpstr 2015/11/19 21:00:24 So, to elaborate on what I was saying earlier, you
dcheng 2015/11/19 21:26:04 This is the only way I could get it to compile: te
vmpstr 2015/11/19 21:28:41 My guess is you didn't put the ", int" part in the
288 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { 327 !std::is_array<U>::value &&
289 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); 328 std::is_convertible<typename scoped_ptr<U, E>::pointer_type,
329 pointer_type>::value &&
330 std::is_convertible<E, D>::value>::type>
331 scoped_ptr& operator=(scoped_ptr<U, E>&& rhs) {
290 impl_.TakeState(&rhs.impl_); 332 impl_.TakeState(&rhs.impl_);
291 return *this; 333 return *this;
292 } 334 }
293 335
294 // operator=. Allows assignment from a nullptr. Deletes the currently owned 336 // operator=. Allows assignment from a nullptr. Deletes the currently owned
295 // object, if any. 337 // object, if any.
296 scoped_ptr& operator=(std::nullptr_t) { 338 scoped_ptr& operator=(std::nullptr_t) {
297 reset(); 339 reset();
298 return *this; 340 return *this;
299 } 341 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 // Forbidden for API compatibility with std::unique_ptr. 397 // Forbidden for API compatibility with std::unique_ptr.
356 explicit scoped_ptr(int disallow_construction_from_null); 398 explicit scoped_ptr(int disallow_construction_from_null);
357 }; 399 };
358 400
359 template <class T, class D> 401 template <class T, class D>
360 class scoped_ptr<T[], D> { 402 class scoped_ptr<T[], D> {
361 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) 403 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
362 404
363 public: 405 public:
364 // The element and deleter types. 406 // The element and deleter types.
365 typedef T element_type; 407 using element_type = T;
366 typedef D deleter_type; 408 using pointer_type = element_type*;
dcheng 2015/11/19 20:49:10 This is for consistency, but probably not needed,
vmpstr 2015/11/19 21:00:24 FWIW, I think reading std::is_convertible<U*, T*>
danakj 2015/11/19 21:03:36 unique_ptr has ::pointer, not pointer_type. and it
dcheng 2015/11/19 21:26:04 Given vmpstr@'s feedback and the fact that our poi
409 using deleter_type = D;
367 410
368 // Constructor. Defaults to initializing with nullptr. 411 // Constructor. Defaults to initializing with nullptr.
369 scoped_ptr() : impl_(nullptr) {} 412 scoped_ptr() : impl_(nullptr) {}
370 413
371 // Constructor. Stores the given array. Note that the argument's type 414 // Constructor. Stores the given array. Note that the argument's type
372 // must exactly match T*. In particular: 415 // must exactly match T*. In particular:
373 // - it cannot be a pointer to a type derived from T, because it is 416 // - it cannot be a pointer to a type derived from T, because it is
374 // inherently unsafe in the general case to access an array through a 417 // inherently unsafe in the general case to access an array through a
375 // pointer whose dynamic type does not match its static type (eg., if 418 // pointer whose dynamic type does not match its static type (eg., if
376 // T and the derived types had different sizes access would be 419 // T and the derived types had different sizes access would be
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 scoped_ptr<T> make_scoped_ptr(T* ptr) { 594 scoped_ptr<T> make_scoped_ptr(T* ptr) {
552 return scoped_ptr<T>(ptr); 595 return scoped_ptr<T>(ptr);
553 } 596 }
554 597
555 template <typename T> 598 template <typename T>
556 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { 599 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
557 return out << p.get(); 600 return out << p.get();
558 } 601 }
559 602
560 #endif // BASE_MEMORY_SCOPED_PTR_H_ 603 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698