blob: 35f4a54ebe40f7a9ae12478a03b0da5671cd47d1 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11// Scopers help you manage ownership of a pointer, helping you easily manage the
12// a pointer within a scope, and automatically destroying the pointer at the
13// end of a scope. There are two main classes you will use, which correspond
14// to the operators new/delete and new[]/delete[].
15//
16// Example usage (scoped_ptr<T>):
17// {
18// scoped_ptr<Foo> foo(new Foo("wee"));
19// } // foo goes out of scope, releasing the pointer with it.
20//
21// {
22// scoped_ptr<Foo> foo; // No pointer managed.
23// foo.reset(new Foo("wee")); // Now a pointer is managed.
24// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
25// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
26// foo->Method(); // Foo::Method() called.
27// foo.get()->Method(); // Foo::Method() called.
28// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
29// // manages a pointer.
30// foo.reset(new Foo("wee4")); // foo manages a pointer again.
31// foo.reset(); // Foo("wee4") destroyed, foo no longer
32// // manages a pointer.
33// } // foo wasn't managing a pointer, so nothing was destroyed.
34//
35// Example usage (scoped_ptr<T[]>):
36// {
37// scoped_ptr<Foo[]> foo(new Foo[100]);
38// foo.get()->Method(); // Foo::Method on the 0th element.
39// foo[10].Method(); // Foo::Method on the 10th element.
40// }
41//
42// These scopers also implement part of the functionality of C++11 unique_ptr
43// in that they are "movable but not copyable." You can use the scopers in
44// the parameter and return types of functions to signify ownership transfer
45// in to and out of a function. When calling a function that has a scoper
46// as the argument type, it must be called with the result of an analogous
47// scoper's Pass() function or another function that generates a temporary;
48// passing by copy will NOT work. Here is an example using scoped_ptr:
49//
50// void TakesOwnership(scoped_ptr<Foo> arg) {
51// // Do something with arg
52// }
53// scoped_ptr<Foo> CreateFoo() {
54// // No need for calling Pass() because we are constructing a temporary
55// // for the return value.
56// return scoped_ptr<Foo>(new Foo("new"));
57// }
58// scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
59// return arg.Pass();
60// }
61//
62// {
63// scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
64// TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
65// scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
66// scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
67// PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
68// }
69//
70// Notice that if you do not call Pass() when returning from PassThru(), or
71// when invoking TakesOwnership(), the code will not compile because scopers
72// are not copyable; they only implement move semantics which require calling
73// the Pass() function to signify a destructive transfer of state. CreateFoo()
74// is different though because we are constructing a temporary on the return
75// line and thus can avoid needing to call Pass().
76//
77// Pass() properly handles upcast in initialization, i.e. you can use a
78// scoped_ptr<Child> to initialize a scoped_ptr<Parent>:
79//
80// scoped_ptr<Foo> foo(new Foo());
81// scoped_ptr<FooParent> parent(foo.Pass());
82//
83// PassAs<>() should be used to upcast return value in return statement:
84//
85// scoped_ptr<Foo> CreateFoo() {
86// scoped_ptr<FooChild> result(new FooChild());
87// return result.PassAs<Foo>();
88// }
89//
90// Note that PassAs<>() is implemented only for scoped_ptr<T>, but not for
91// scoped_ptr<T[]>. This is because casting array pointers may not be safe.
92
93#ifndef WEBRTC_BASE_SCOPED_PTR_H__
94#define WEBRTC_BASE_SCOPED_PTR_H__
95
96#include <stddef.h> // for ptrdiff_t
97#include <stdlib.h> // for free() decl
98
99#include <algorithm> // For std::swap().
100
101#include "webrtc/base/common.h" // for ASSERT
kwiberg@webrtc.orgaa21f272014-12-19 14:35:57 +0000102#include "webrtc/base/move.h" // for RTC_MOVE_ONLY_TYPE_FOR_CPP_03
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000103#include "webrtc/base/template_util.h" // for is_convertible, is_array
104
105#ifdef WEBRTC_WIN
106namespace std { using ::ptrdiff_t; };
107#endif // WEBRTC_WIN
108
109namespace rtc {
110
111// Function object which deletes its parameter, which must be a pointer.
112// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
113// invokes 'delete'. The default deleter for scoped_ptr<T>.
114template <class T>
115struct DefaultDeleter {
116 DefaultDeleter() {}
117 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
118 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
119 // if U* is implicitly convertible to T* and U is not an array type.
120 //
121 // Correct implementation should use SFINAE to disable this
122 // constructor. However, since there are no other 1-argument constructors,
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000123 // using a static_assert based on is_convertible<> and requiring
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124 // complete types is simpler and will cause compile failures for equivalent
125 // misuses.
126 //
127 // Note, the is_convertible<U*, T*> check also ensures that U is not an
128 // array. T is guaranteed to be a non-array, so any U* where U is an array
129 // cannot convert to T*.
130 enum { T_must_be_complete = sizeof(T) };
131 enum { U_must_be_complete = sizeof(U) };
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000132 static_assert(rtc::is_convertible<U*, T*>::value,
133 "U* must implicitly convert to T*");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134 }
135 inline void operator()(T* ptr) const {
136 enum { type_must_be_complete = sizeof(T) };
137 delete ptr;
138 }
139};
140
141// Specialization of DefaultDeleter for array types.
142template <class T>
143struct DefaultDeleter<T[]> {
144 inline void operator()(T* ptr) const {
145 enum { type_must_be_complete = sizeof(T) };
146 delete[] ptr;
147 }
148
149 private:
150 // Disable this operator for any U != T because it is undefined to execute
151 // an array delete when the static type of the array mismatches the dynamic
152 // type.
153 //
154 // References:
155 // C++98 [expr.delete]p3
156 // http://cplusplus.github.com/LWG/lwg-defects.html#938
157 template <typename U> void operator()(U* array) const;
158};
159
160template <class T, int n>
161struct DefaultDeleter<T[n]> {
162 // Never allow someone to declare something like scoped_ptr<int[10]>.
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000163 static_assert(sizeof(T) == -1, "do not use array with size as type");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000164};
165
166// Function object which invokes 'free' on its parameter, which must be
167// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
168//
169// scoped_ptr<int, rtc::FreeDeleter> foo_ptr(
170// static_cast<int*>(malloc(sizeof(int))));
171struct FreeDeleter {
172 inline void operator()(void* ptr) const {
173 free(ptr);
174 }
175};
176
177namespace internal {
178
179// Minimal implementation of the core logic of scoped_ptr, suitable for
180// reuse in both scoped_ptr and its specializations.
181template <class T, class D>
182class scoped_ptr_impl {
183 public:
184 explicit scoped_ptr_impl(T* p) : data_(p) { }
185
186 // Initializer for deleters that have data parameters.
187 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
188
189 // Templated constructor that destructively takes the value from another
190 // scoped_ptr_impl.
191 template <typename U, typename V>
192 scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
193 : data_(other->release(), other->get_deleter()) {
194 // We do not support move-only deleters. We could modify our move
195 // emulation to have rtc::subtle::move() and
196 // rtc::subtle::forward()
197 // functions that are imperfect emulations of their C++11 equivalents,
198 // but until there's a requirement, just assume deleters are copyable.
199 }
200
201 template <typename U, typename V>
202 void TakeState(scoped_ptr_impl<U, V>* other) {
203 // See comment in templated constructor above regarding lack of support
204 // for move-only deleters.
205 reset(other->release());
206 get_deleter() = other->get_deleter();
207 }
208
209 ~scoped_ptr_impl() {
210 if (data_.ptr != NULL) {
211 // Not using get_deleter() saves one function call in non-optimized
212 // builds.
213 static_cast<D&>(data_)(data_.ptr);
214 }
215 }
216
217 void reset(T* p) {
218 // This is a self-reset, which is no longer allowed: http://crbug.com/162971
219 if (p != NULL && p == data_.ptr)
220 abort();
221
222 // Note that running data_.ptr = p can lead to undefined behavior if
223 // get_deleter()(get()) deletes this. In order to pevent this, reset()
224 // should update the stored pointer before deleting its old value.
225 //
226 // However, changing reset() to use that behavior may cause current code to
227 // break in unexpected ways. If the destruction of the owned object
228 // dereferences the scoped_ptr when it is destroyed by a call to reset(),
229 // then it will incorrectly dispatch calls to |p| rather than the original
230 // value of |data_.ptr|.
231 //
232 // During the transition period, set the stored pointer to NULL while
233 // deleting the object. Eventually, this safety check will be removed to
234 // prevent the scenario initially described from occuring and
235 // http://crbug.com/176091 can be closed.
236 T* old = data_.ptr;
237 data_.ptr = NULL;
238 if (old != NULL)
239 static_cast<D&>(data_)(old);
240 data_.ptr = p;
241 }
242
243 T* get() const { return data_.ptr; }
244
245 D& get_deleter() { return data_; }
246 const D& get_deleter() const { return data_; }
247
248 void swap(scoped_ptr_impl& p2) {
249 // Standard swap idiom: 'using std::swap' ensures that std::swap is
250 // present in the overload set, but we call swap unqualified so that
251 // any more-specific overloads can be used, if available.
252 using std::swap;
253 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
254 swap(data_.ptr, p2.data_.ptr);
255 }
256
257 T* release() {
258 T* old_ptr = data_.ptr;
259 data_.ptr = NULL;
260 return old_ptr;
261 }
262
263 T** accept() {
264 reset(NULL);
265 return &(data_.ptr);
266 }
267
268 T** use() {
269 return &(data_.ptr);
270 }
271
272 private:
273 // Needed to allow type-converting constructor.
274 template <typename U, typename V> friend class scoped_ptr_impl;
275
276 // Use the empty base class optimization to allow us to have a D
277 // member, while avoiding any space overhead for it when D is an
278 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
279 // discussion of this technique.
280 struct Data : public D {
281 explicit Data(T* ptr_in) : ptr(ptr_in) {}
282 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
283 T* ptr;
284 };
285
286 Data data_;
287
288 DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
289};
290
291} // namespace internal
292
293// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
294// automatically deletes the pointer it holds (if any).
295// That is, scoped_ptr<T> owns the T object that it points to.
296// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
297// Also like T*, scoped_ptr<T> is thread-compatible, and once you
298// dereference it, you get the thread safety guarantees of T.
299//
300// The size of scoped_ptr is small. On most compilers, when using the
301// DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
302// increase the size proportional to whatever state they need to have. See
303// comments inside scoped_ptr_impl<> for details.
304//
305// Current implementation targets having a strict subset of C++11's
306// unique_ptr<> features. Known deficiencies include not supporting move-only
307// deleteres, function pointers as deleters, and deleters with reference
308// types.
309template <class T, class D = rtc::DefaultDeleter<T> >
310class scoped_ptr {
kwiberg@webrtc.orgaa21f272014-12-19 14:35:57 +0000311 RTC_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000312
313 public:
314 // The element and deleter types.
315 typedef T element_type;
316 typedef D deleter_type;
317
318 // Constructor. Defaults to initializing with NULL.
319 scoped_ptr() : impl_(NULL) { }
320
321 // Constructor. Takes ownership of p.
322 explicit scoped_ptr(element_type* p) : impl_(p) { }
323
324 // Constructor. Allows initialization of a stateful deleter.
325 scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
326
327 // Constructor. Allows construction from a scoped_ptr rvalue for a
328 // convertible type and deleter.
329 //
330 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
331 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
332 // has different post-conditions if D is a reference type. Since this
333 // implementation does not support deleters with reference type,
334 // we do not need a separate move constructor allowing us to avoid one
335 // use of SFINAE. You only need to care about this if you modify the
336 // implementation of scoped_ptr.
337 template <typename U, typename V>
338 scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000339 static_assert(!rtc::is_array<U>::value, "U cannot be an array");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000340 }
341
342 // Constructor. Move constructor for C++03 move emulation of this type.
343 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
344
345 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
346 // type and deleter.
347 //
348 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
349 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
350 // form has different requirements on for move-only Deleters. Since this
351 // implementation does not support move-only Deleters, we do not need a
352 // separate move assignment operator allowing us to avoid one use of SFINAE.
353 // You only need to care about this if you modify the implementation of
354 // scoped_ptr.
355 template <typename U, typename V>
356 scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
kwiberg@webrtc.org2ebfac52015-01-14 10:51:54 +0000357 static_assert(!rtc::is_array<U>::value, "U cannot be an array");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000358 impl_.TakeState(&rhs.impl_);
359 return *this;
360 }
361
362 // Reset. Deletes the currently owned object, if any.
363 // Then takes ownership of a new object, if given.
364 void reset(element_type* p = NULL) { impl_.reset(p); }
365
366 // Accessors to get the owned object.
367 // operator* and operator-> will assert() if there is no current object.
368 element_type& operator*() const {
369 ASSERT(impl_.get() != NULL);
370 return *impl_.get();
371 }
372 element_type* operator->() const {
373 ASSERT(impl_.get() != NULL);
374 return impl_.get();
375 }
376 element_type* get() const { return impl_.get(); }
377
378 // Access to the deleter.
379 deleter_type& get_deleter() { return impl_.get_deleter(); }
380 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
381
382 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
383 // implicitly convertible to a real bool (which is dangerous).
384 //
385 // Note that this trick is only safe when the == and != operators
386 // are declared explicitly, as otherwise "scoped_ptr1 ==
387 // scoped_ptr2" will compile but do the wrong thing (i.e., convert
388 // to Testable and then do the comparison).
389 private:
390 typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
391 scoped_ptr::*Testable;
392
393 public:
394 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
395
396 // Comparison operators.
397 // These return whether two scoped_ptr refer to the same object, not just to
398 // two different but equal objects.
399 bool operator==(const element_type* p) const { return impl_.get() == p; }
400 bool operator!=(const element_type* p) const { return impl_.get() != p; }
401
402 // Swap two scoped pointers.
403 void swap(scoped_ptr& p2) {
404 impl_.swap(p2.impl_);
405 }
406
407 // Release a pointer.
408 // The return value is the current pointer held by this object.
409 // If this object holds a NULL pointer, the return value is NULL.
410 // After this operation, this object will hold a NULL pointer,
411 // and will not own the object any more.
412 element_type* release() WARN_UNUSED_RESULT {
413 return impl_.release();
414 }
415
416 // Delete the currently held pointer and return a pointer
417 // to allow overwriting of the current pointer address.
418 element_type** accept() WARN_UNUSED_RESULT {
419 return impl_.accept();
420 }
421
422 // Return a pointer to the current pointer address.
423 element_type** use() WARN_UNUSED_RESULT {
424 return impl_.use();
425 }
426
427 // C++98 doesn't support functions templates with default parameters which
428 // makes it hard to write a PassAs() that understands converting the deleter
429 // while preserving simple calling semantics.
430 //
431 // Until there is a use case for PassAs() with custom deleters, just ignore
432 // the custom deleter.
433 template <typename PassAsType>
434 scoped_ptr<PassAsType> PassAs() {
435 return scoped_ptr<PassAsType>(Pass());
436 }
437
438 private:
439 // Needed to reach into |impl_| in the constructor.
440 template <typename U, typename V> friend class scoped_ptr;
441 rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
442
443 // Forbidden for API compatibility with std::unique_ptr.
444 explicit scoped_ptr(int disallow_construction_from_null);
445
446 // Forbid comparison of scoped_ptr types. If U != T, it totally
447 // doesn't make sense, and if U == T, it still doesn't make sense
448 // because you should never have the same object owned by two different
449 // scoped_ptrs.
450 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
451 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
452};
453
454template <class T, class D>
455class scoped_ptr<T[], D> {
kwiberg@webrtc.orgaa21f272014-12-19 14:35:57 +0000456 RTC_MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000457
458 public:
459 // The element and deleter types.
460 typedef T element_type;
461 typedef D deleter_type;
462
463 // Constructor. Defaults to initializing with NULL.
464 scoped_ptr() : impl_(NULL) { }
465
466 // Constructor. Stores the given array. Note that the argument's type
467 // must exactly match T*. In particular:
468 // - it cannot be a pointer to a type derived from T, because it is
469 // inherently unsafe in the general case to access an array through a
470 // pointer whose dynamic type does not match its static type (eg., if
471 // T and the derived types had different sizes access would be
472 // incorrectly calculated). Deletion is also always undefined
473 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
474 // - it cannot be NULL, because NULL is an integral expression, not a
475 // pointer to T. Use the no-argument version instead of explicitly
476 // passing NULL.
477 // - it cannot be const-qualified differently from T per unique_ptr spec
478 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
479 // to work around this may use implicit_cast<const T*>().
480 // However, because of the first bullet in this comment, users MUST
481 // NOT use implicit_cast<Base*>() to upcast the static type of the array.
482 explicit scoped_ptr(element_type* array) : impl_(array) { }
483
484 // Constructor. Move constructor for C++03 move emulation of this type.
485 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
486
487 // operator=. Move operator= for C++03 move emulation of this type.
488 scoped_ptr& operator=(RValue rhs) {
489 impl_.TakeState(&rhs.object->impl_);
490 return *this;
491 }
492
493 // Reset. Deletes the currently owned array, if any.
494 // Then takes ownership of a new object, if given.
495 void reset(element_type* array = NULL) { impl_.reset(array); }
496
497 // Accessors to get the owned array.
498 element_type& operator[](size_t i) const {
499 ASSERT(impl_.get() != NULL);
500 return impl_.get()[i];
501 }
502 element_type* get() const { return impl_.get(); }
503
504 // Access to the deleter.
505 deleter_type& get_deleter() { return impl_.get_deleter(); }
506 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
507
508 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
509 // implicitly convertible to a real bool (which is dangerous).
510 private:
511 typedef rtc::internal::scoped_ptr_impl<element_type, deleter_type>
512 scoped_ptr::*Testable;
513
514 public:
515 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
516
517 // Comparison operators.
518 // These return whether two scoped_ptr refer to the same object, not just to
519 // two different but equal objects.
520 bool operator==(element_type* array) const { return impl_.get() == array; }
521 bool operator!=(element_type* array) const { return impl_.get() != array; }
522
523 // Swap two scoped pointers.
524 void swap(scoped_ptr& p2) {
525 impl_.swap(p2.impl_);
526 }
527
528 // Release a pointer.
529 // The return value is the current pointer held by this object.
530 // If this object holds a NULL pointer, the return value is NULL.
531 // After this operation, this object will hold a NULL pointer,
532 // and will not own the object any more.
533 element_type* release() WARN_UNUSED_RESULT {
534 return impl_.release();
535 }
536
537 // Delete the currently held pointer and return a pointer
538 // to allow overwriting of the current pointer address.
539 element_type** accept() WARN_UNUSED_RESULT {
540 return impl_.accept();
541 }
542
543 // Return a pointer to the current pointer address.
544 element_type** use() WARN_UNUSED_RESULT {
545 return impl_.use();
546 }
547
548 private:
549 // Force element_type to be a complete type.
550 enum { type_must_be_complete = sizeof(element_type) };
551
552 // Actually hold the data.
553 rtc::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
554
555 // Disable initialization from any type other than element_type*, by
556 // providing a constructor that matches such an initialization, but is
557 // private and has no definition. This is disabled because it is not safe to
558 // call delete[] on an array whose static type does not match its dynamic
559 // type.
560 template <typename U> explicit scoped_ptr(U* array);
561 explicit scoped_ptr(int disallow_construction_from_null);
562
563 // Disable reset() from any type other than element_type*, for the same
564 // reasons as the constructor above.
565 template <typename U> void reset(U* array);
566 void reset(int disallow_reset_from_null);
567
568 // Forbid comparison of scoped_ptr types. If U != T, it totally
569 // doesn't make sense, and if U == T, it still doesn't make sense
570 // because you should never have the same object owned by two different
571 // scoped_ptrs.
572 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
573 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
574};
575
576} // namespace rtc
577
578// Free functions
579template <class T, class D>
580void swap(rtc::scoped_ptr<T, D>& p1, rtc::scoped_ptr<T, D>& p2) {
581 p1.swap(p2);
582}
583
584template <class T, class D>
585bool operator==(T* p1, const rtc::scoped_ptr<T, D>& p2) {
586 return p1 == p2.get();
587}
588
589template <class T, class D>
590bool operator!=(T* p1, const rtc::scoped_ptr<T, D>& p2) {
591 return p1 != p2.get();
592}
593
594#endif // #ifndef WEBRTC_BASE_SCOPED_PTR_H__