1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (c) Electronic Arts Inc. All rights reserved. 3 /////////////////////////////////////////////////////////////////////////////// 4 5 6 #ifndef EASTL_UNIQUE_PTR_H 7 #define EASTL_UNIQUE_PTR_H 8 9 10 #include <EABase/nullptr.h> 11 #include <EASTL/internal/config.h> 12 #include <EASTL/internal/smart_ptr.h> // Defines smart_ptr_deleter 13 #include <EASTL/internal/move_help.h> // Defines EASTL_MOVE 14 #include <EASTL/type_traits.h> 15 #include <EASTL/functional.h> 16 #include <EASTL/bonus/compressed_pair.h> 17 #include <stddef.h> 18 19 #if defined(EA_PRAGMA_ONCE_SUPPORTED) 20 #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. 21 #endif 22 23 24 namespace eastl 25 { 26 /// class unique_ptr 27 /// 28 /// This class implements a unique_ptr template. This is a class which is 29 /// similar to the C++ auto_ptr template, except that it prohibits copying 30 /// of itself, for safety. 31 /// 32 /// More specifically, the unique_ptr class template stores a pointer to a 33 /// dynamically allocated object. The object pointed to is automatically 34 /// deleted on destructor of unique_ptr or can be manually deleted via the 35 /// unique_ptr::reset function. 36 /// 37 /// Memory allocation notes: 38 /// unique_ptr doesn't allocate memory; all allocated pointers are externally 39 /// derived. unique_ptr does deallocate memory, though always through the 40 /// user-provided deleter. You need to make sure you are consistent in providing 41 /// a deleter which frees memory in a way that matches how it was originally allocated. 42 /// Deleters have instance information and are moved between containers the same way 43 /// the allocated pointers are. Thus you can allocate memory via some heap and 44 /// provide a deleter which contains a pointer to that same heap, and regardless 45 /// of what you do with the unique_ptr, including moving it to another unique_ptr, 46 /// the deletion will use the originally provided heap. 47 /// 48 /// Example usage: 49 /// unique_ptr<int> p(new int); 50 /// *p = 4; 51 /// 52 /// unique_ptr<int[]> pArray(new int[4]); 53 /// p[0] = 4; 54 /// 55 /// Type completeness requirements 56 /// http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t/6089065#6089065 57 /// Here is a table which documents several members of shared_ptr and unique_ptr with respect to completeness requirements. 58 /// If the member requires a complete type, the entry has a "C", otherwise the table entry is filled with "I". 59 /// 60 /// unique_ptr shared_ptr 61 /// +------------------------+---------------+---------------+ 62 /// | P() | I | I | 63 /// | default constructor | | | 64 /// +------------------------+---------------+---------------+ 65 /// | P(const P&) | N/A | I | 66 /// | copy constructor | | | 67 /// +------------------------+---------------+---------------+ 68 /// | P(P&&) | I | I | 69 /// | move constructor | | | 70 /// +------------------------+---------------+---------------+ 71 /// | ~P() | C | I | 72 /// | destructor | | | 73 /// +------------------------+---------------+---------------+ 74 /// | P(A*) | I | C | 75 /// +------------------------+---------------+---------------+ 76 /// | operator=(const P&) | N/A | I | 77 /// | copy assignment | | | 78 /// +------------------------+---------------+---------------+ 79 /// | operator=(P&&) | C | I | 80 /// | move assignment | | | 81 /// +------------------------+---------------+---------------+ 82 /// | reset() | C | I | 83 /// +------------------------+---------------+---------------+ 84 /// | reset(A*) | C | C | 85 /// +------------------------+---------------+---------------+ 86 /// 87 template <typename T, typename Deleter = eastl::default_delete<T> > 88 class unique_ptr 89 { 90 public: 91 typedef Deleter deleter_type; 92 typedef T element_type; 93 typedef unique_ptr<element_type, deleter_type> this_type; 94 typedef typename Internal::unique_pointer_type<element_type, deleter_type>::type pointer; 95 96 public: 97 /// unique_ptr 98 /// Construct a unique_ptr from a pointer allocated via new. 99 /// Example usage: 100 /// unique_ptr<int> ptr; unique_ptr()101 EA_CPP14_CONSTEXPR unique_ptr() EA_NOEXCEPT 102 : mPair(pointer()) 103 { 104 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 105 } 106 107 /// unique_ptr 108 /// Construct a unique_ptr from a null pointer. 109 /// Example usage: 110 /// unique_ptr<int> ptr(nullptr); unique_ptr(std::nullptr_t)111 EA_CPP14_CONSTEXPR unique_ptr(std::nullptr_t) EA_NOEXCEPT 112 : mPair(pointer()) 113 { 114 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 115 } 116 117 /// unique_ptr 118 /// Construct a unique_ptr from a pointer allocated via new. 119 /// Example usage: 120 /// unique_ptr<int> ptr(new int(3)); unique_ptr(pointer pValue)121 explicit unique_ptr(pointer pValue) EA_NOEXCEPT 122 : mPair(pValue) 123 { 124 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 125 } 126 127 /// unique_ptr 128 /// Constructs a unique_ptr with the owner pointer and deleter specified 129 /// Example usage: 130 /// eastl::smart_ptr_deleter<int> del; 131 /// unique_ptr<int> ptr(new int(3), del); unique_ptr(pointer pValue,typename eastl::conditional<eastl::is_reference<deleter_type>::value,deleter_type,typename eastl::add_lvalue_reference<const deleter_type>::type>::type deleter)132 unique_ptr(pointer pValue, typename eastl::conditional<eastl::is_reference<deleter_type>::value, deleter_type, typename eastl::add_lvalue_reference<const deleter_type>::type>::type deleter) EA_NOEXCEPT 133 : mPair(pValue, deleter) {} 134 135 /// unique_ptr 136 /// Constructs a unique_ptr with the owned pointer and deleter specified (rvalue) 137 /// Example usage: 138 /// unique_ptr<int> ptr(new int(3), eastl::smart_ptr_deleter<int>()); unique_ptr(pointer pValue,typename eastl::remove_reference<deleter_type>::type && deleter)139 unique_ptr(pointer pValue, typename eastl::remove_reference<deleter_type>::type&& deleter) EA_NOEXCEPT 140 : mPair(pValue, eastl::move(deleter)) 141 { 142 static_assert(!eastl::is_reference<deleter_type>::value, "deleter_type reference refers to an rvalue deleter. The reference will probably become invalid before used. Change the deleter_type to not be a reference or construct with permanent deleter."); 143 } 144 145 /// unique_ptr 146 /// Move constructor 147 /// Example usage: 148 /// unique_ptr<int> ptr(new int(3)); 149 /// unique_ptr<int> newPtr = eastl::move(ptr); unique_ptr(this_type && x)150 unique_ptr(this_type&& x) EA_NOEXCEPT 151 : mPair(x.release(), eastl::forward<deleter_type>(x.get_deleter())) {} 152 153 /// unique_ptr 154 /// Move constructor 155 /// Example usage: 156 /// unique_ptr<int> ptr(new int(3)); 157 /// unique_ptr<int> newPtr = eastl::move(ptr); 158 template <typename U, typename E> 159 unique_ptr(unique_ptr<U, E>&& u, typename enable_if<!is_array<U>::value && is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && is_convertible<E, deleter_type>::value && (is_same<deleter_type, E>::value || !is_reference<deleter_type>::value)>::type* = 0) EA_NOEXCEPT 160 : mPair(u.release(), eastl::forward<E>(u.get_deleter())) {} 161 162 /// unique_ptr 163 /// Move assignment 164 /// Example usage: 165 /// unique_ptr<int> ptr(new int(3)); 166 /// unique_ptr<int> newPtr(new int(4)); 167 /// ptr = eastl::move(newPtr); // Deletes int(3) and assigns mpValue to int(4) 168 this_type& operator=(this_type&& x) EA_NOEXCEPT 169 { 170 reset(x.release()); 171 mPair.second() = eastl::move(eastl::forward<deleter_type>(x.get_deleter())); 172 return *this; 173 } 174 175 /// unique_ptr 176 /// Move assignment 177 template <typename U, typename E> 178 typename enable_if<!is_array<U>::value && is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value && is_assignable<deleter_type&, E&&>::value, this_type&>::type 179 operator=(unique_ptr<U, E>&& u) EA_NOEXCEPT 180 { 181 reset(u.release()); 182 mPair.second() = eastl::move(eastl::forward<E>(u.get_deleter())); 183 return *this; 184 } 185 186 /// operator=(nullptr_t) 187 this_type& operator=(std::nullptr_t) EA_NOEXCEPT 188 { 189 reset(); 190 return *this; 191 } 192 193 /// ~unique_ptr 194 /// Destroys the owned pointer. The destructor for the object 195 /// referred to by the owned pointer will be called. ~unique_ptr()196 ~unique_ptr() EA_NOEXCEPT 197 { 198 reset(); 199 } 200 201 /// reset 202 /// Deletes the owned pointer and takes ownership of the 203 /// passed in pointer. If the passed in pointer is the same 204 /// as the owned pointer, nothing is done. 205 /// Example usage: 206 /// unique_ptr<int> ptr(new int(3)); 207 /// ptr.reset(new int(4)); // deletes int(3) 208 /// ptr.reset(NULL); // deletes int(4) 209 void reset(pointer pValue = pointer()) EA_NOEXCEPT 210 { 211 if (pValue != mPair.first()) 212 { 213 if (mPair.first()) 214 get_deleter()(mPair.first()); 215 216 mPair.first() = pValue; 217 } 218 } 219 220 /// release 221 /// This simply forgets the owned pointer. It doesn't 222 /// free it but rather assumes that the user does. 223 /// Example usage: 224 /// unique_ptr<int> ptr(new int(3)); 225 /// int* pInt = ptr.release(); 226 /// delete pInt; release()227 pointer release() EA_NOEXCEPT 228 { 229 pointer const pTemp = mPair.first(); 230 mPair.first() = pointer(); 231 return pTemp; 232 } 233 234 /// detach 235 /// For backwards-compatibility with pre-C++11 code. detach()236 pointer detach() EA_NOEXCEPT { return release(); } 237 238 /// swap 239 /// Exchanges the owned pointer beween two unique_ptr objects. swap(this_type & x)240 void swap(this_type& x) EA_NOEXCEPT 241 { 242 mPair.swap(x.mPair); 243 } 244 245 /// operator* 246 /// Returns the owner pointer dereferenced. 247 /// Example usage: 248 /// unique_ptr<int> ptr(new int(3)); 249 /// int x = *ptr; 250 typename add_lvalue_reference<T>::type operator*() const // Not noexcept, because the pointer may be NULL. 251 { 252 return *mPair.first(); 253 } 254 255 /// operator-> 256 /// Allows access to the owned pointer via operator->() 257 /// Example usage: 258 /// struct X{ void DoSomething(); }; 259 /// unique_ptr<int> ptr(new X); 260 /// ptr->DoSomething(); 261 pointer operator->() const EA_NOEXCEPT 262 { 263 return mPair.first(); 264 } 265 266 /// get 267 /// Returns the owned pointer. Note that this class does 268 /// not provide an operator T() function. This is because such 269 /// a thing (automatic conversion) is deemed unsafe. 270 /// Example usage: 271 /// struct X{ void DoSomething(); }; 272 /// unique_ptr<int> ptr(new X); 273 /// X* pX = ptr.get(); 274 /// pX->DoSomething(); get()275 pointer get() const EA_NOEXCEPT 276 { 277 return mPair.first(); 278 } 279 280 /// get_deleter 281 /// Returns the deleter used to delete the owned pointer 282 /// Example usage: 283 /// unique_ptr<int> ptr(new int(3)); 284 /// eastl::smart_ptr_deleter<int>& del = ptr.get_deleter(); get_deleter()285 deleter_type& get_deleter() EA_NOEXCEPT 286 { 287 return mPair.second(); 288 } 289 290 /// get_deleter 291 /// Const version for getting the deleter get_deleter()292 const deleter_type& get_deleter() const EA_NOEXCEPT 293 { 294 return mPair.second(); 295 } 296 297 #ifdef EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS 298 /// Note that below we do not use operator bool(). The reason for this 299 /// is that booleans automatically convert up to short, int, float, etc. 300 /// The result is that this: if(uniquePtr == 1) would yield true (bad). 301 typedef T* (this_type::*bool_)() const; bool_()302 operator bool_() const EA_NOEXCEPT 303 { 304 if(mPair.first()) 305 return &this_type::get; 306 return NULL; 307 } 308 309 bool operator!() const EA_NOEXCEPT 310 { 311 return (mPair.first() == pointer()); 312 } 313 #else 314 /// operator bool 315 /// Allows for using a unique_ptr as a boolean. 316 /// Example usage: 317 /// unique_ptr<int> ptr(new int(3)); 318 /// if(ptr) 319 /// ++*ptr; 320 /// 321 explicit operator bool() const EA_NOEXCEPT 322 { 323 return (mPair.first() != pointer()); 324 } 325 #endif 326 327 /// These functions are deleted in order to prevent copying, for safety. 328 unique_ptr(const this_type&) = delete; 329 unique_ptr& operator=(const this_type&) = delete; 330 unique_ptr& operator=(pointer pValue) = delete; 331 332 protected: 333 eastl::compressed_pair<pointer, deleter_type> mPair; 334 }; // class unique_ptr 335 336 337 338 /// unique_ptr specialization for unbounded arrays. 339 /// 340 /// Differences from unique_ptr<T>: 341 /// - Conversions between different types of unique_ptr<T[], D> or to or 342 /// from the non-array forms of unique_ptr produce an ill-formed program. 343 /// - Pointers to types derived from T are rejected by the constructors, and by reset. 344 /// - The observers operator* and operator-> are not provided. 345 /// - The indexing observer operator[] is provided. 346 /// - The default deleter will call delete[]. 347 /// 348 /// It's not possible to create a unique_ptr for arrays of a known bound (e.g. int[4] as opposed to int[]). 349 /// 350 /// Example usage: 351 /// unique_ptr<int[]> ptr(new int[10]); 352 /// ptr[4] = 4; 353 /// 354 template <typename T, typename Deleter> 355 class unique_ptr<T[], Deleter> 356 { 357 public: 358 typedef Deleter deleter_type; 359 typedef T element_type; 360 typedef unique_ptr<element_type[], deleter_type> this_type; 361 typedef typename Internal::unique_pointer_type<element_type, deleter_type>::type pointer; 362 363 public: unique_ptr()364 EA_CPP14_CONSTEXPR unique_ptr() EA_NOEXCEPT 365 : mPair(pointer()) 366 { 367 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 368 } 369 unique_ptr(std::nullptr_t)370 EA_CPP14_CONSTEXPR unique_ptr(std::nullptr_t) EA_NOEXCEPT 371 : mPair(pointer()) 372 { 373 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 374 } 375 376 template <typename P> // Pointers to types derived from T are rejected by the constructors, and by reset. 377 explicit unique_ptr(P pArray, typename eastl::enable_if<Internal::is_array_cv_convertible<P, pointer>::value>::type* = 0) EA_NOEXCEPT mPair(pArray)378 : mPair(pArray) 379 { 380 static_assert(!eastl::is_pointer<deleter_type>::value, "unique_ptr deleter default-constructed with null pointer. Use a different constructor or change your deleter to a class."); 381 } 382 383 template <typename P> 384 unique_ptr(P pArray, typename eastl::conditional<eastl::is_reference<deleter_type>::value, deleter_type, 385 typename eastl::add_lvalue_reference<const deleter_type>::type>::type deleter, 386 typename eastl::enable_if<Internal::is_array_cv_convertible<P, pointer>::value>::type* = 0) EA_NOEXCEPT mPair(pArray,deleter)387 : mPair(pArray, deleter) {} 388 389 template <typename P> 390 unique_ptr(P pArray, typename eastl::remove_reference<deleter_type>::type&& deleter, typename eastl::enable_if<Internal::is_array_cv_convertible<P, pointer>::value>::type* = 0) EA_NOEXCEPT mPair(pArray,eastl::move (deleter))391 : mPair(pArray, eastl::move(deleter)) 392 { 393 static_assert(!eastl::is_reference<deleter_type>::value, "deleter_type reference refers to an rvalue deleter. The reference will probably become invalid before used. Change the deleter_type to not be a reference or construct with permanent deleter."); 394 } 395 unique_ptr(this_type && x)396 unique_ptr(this_type&& x) EA_NOEXCEPT 397 : mPair(x.release(), eastl::forward<deleter_type>(x.get_deleter())) {} 398 399 template <typename U, typename E> 400 unique_ptr(unique_ptr<U, E>&& u, typename enable_if<Internal::is_safe_array_conversion<T, pointer, U, typename unique_ptr<U, E>::pointer>::value && 401 eastl::is_convertible<E, deleter_type>::value && 402 (!eastl::is_reference<deleter_type>::value || eastl::is_same<E, deleter_type>::value)>::type* = 0) EA_NOEXCEPT 403 : mPair(u.release(), eastl::forward<E>(u.get_deleter())) {} 404 405 this_type& operator=(this_type&& x) EA_NOEXCEPT 406 { 407 reset(x.release()); 408 mPair.second() = eastl::move(eastl::forward<deleter_type>(x.get_deleter())); 409 return *this; 410 } 411 412 template <typename U, typename E> 413 typename enable_if<Internal::is_safe_array_conversion<T, pointer, U, typename unique_ptr<U, E>::pointer>::value && is_assignable<deleter_type&, E&&>::value, this_type&>::type 414 operator=(unique_ptr<U, E>&& u) EA_NOEXCEPT 415 { 416 reset(u.release()); 417 mPair.second() = eastl::move(eastl::forward<E>(u.get_deleter())); 418 return *this; 419 } 420 421 this_type& operator=(std::nullptr_t) EA_NOEXCEPT 422 { 423 reset(); 424 return *this; 425 } 426 ~unique_ptr()427 ~unique_ptr() EA_NOEXCEPT 428 { 429 reset(); 430 } 431 432 void reset(pointer pArray = pointer()) EA_NOEXCEPT 433 { 434 if(pArray != mPair.first()) 435 { 436 get_deleter()(mPair.first()); 437 mPair.first() = pArray; 438 } 439 } 440 release()441 pointer release() EA_NOEXCEPT 442 { 443 pointer const pTemp = mPair.first(); 444 mPair.first() = pointer(); 445 return pTemp; 446 } 447 448 /// detach 449 /// For backwards-compatibility with pre-C++11 code. detach()450 pointer detach() EA_NOEXCEPT { return release(); } 451 swap(this_type & x)452 void swap(this_type& x) EA_NOEXCEPT 453 { 454 mPair.swap(x.mPair); 455 } 456 457 /// operator[] 458 /// Returns a reference to the specified item in the owned pointer 459 /// array. 460 /// Example usage: 461 /// unique_ptr<int> ptr(new int[6]); 462 /// int x = ptr[2]; 463 typename add_lvalue_reference<T>::type operator[](ptrdiff_t i) const 464 { 465 // assert(mpArray && (i >= 0)); 466 return mPair.first()[i]; 467 } 468 get()469 pointer get() const EA_NOEXCEPT 470 { 471 return mPair.first(); 472 } 473 get_deleter()474 deleter_type& get_deleter() EA_NOEXCEPT 475 { 476 return mPair.second(); 477 } 478 get_deleter()479 const deleter_type& get_deleter() const EA_NOEXCEPT 480 { 481 return mPair.second(); 482 } 483 484 #ifdef EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS 485 typedef T* (this_type::*bool_)() const; bool_()486 operator bool_() const EA_NOEXCEPT 487 { 488 if(mPair.first()) 489 return &this_type::get; 490 return NULL; 491 } 492 493 bool operator!() const EA_NOEXCEPT 494 { 495 return (mPair.first() == pointer()); 496 } 497 #else 498 explicit operator bool() const EA_NOEXCEPT 499 { 500 return (mPair.first() != pointer()); 501 } 502 #endif 503 504 /// These functions are deleted in order to prevent copying, for safety. 505 unique_ptr(const this_type&) = delete; 506 unique_ptr& operator=(const this_type&) = delete; 507 unique_ptr& operator=(pointer pArray) = delete; 508 509 protected: 510 eastl::compressed_pair<pointer, deleter_type> mPair; 511 }; 512 513 514 515 /// make_unique 516 /// 517 /// The C++11 Standard doesn't have make_unique, but there's no agreed reason as to why. 518 /// http://stackoverflow.com/questions/12580432/why-does-c11-have-make-shared-but-not-make-unique 519 /// http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ 520 /// Herb's solution is OK but doesn't support unique_ptr<[]> (array version). We do the same 521 /// thing libc++ does and make a specialization of make_unique for arrays. 522 /// 523 /// make_unique has two cases where you can't use it and need to directly use unique_ptr: 524 /// - You need to construct the unique_ptr with a raw pointer. 525 /// - You need to specify a custom deleter. 526 /// 527 /// Note: This function uses global new T by default to create the ptr instance, as per 528 /// the C++11 Standard make_shared_ptr. 529 /// 530 /// Example usage: 531 /// struct Test{ Test(int, int){} }; 532 /// auto p = make_unique<Test>(1, 2); 533 /// 534 /// auto pArray = make_unique<Test[]>(4); 535 /// 536 namespace Internal 537 { 538 template <typename T> 539 struct unique_type 540 { typedef unique_ptr<T> unique_type_single; }; 541 542 template <typename T> 543 struct unique_type<T[]> 544 { typedef unique_ptr<T[]> unique_type_unbounded_array; }; 545 546 template <typename T, size_t N> 547 struct unique_type<T[N]> 548 { typedef void unique_type_bounded_array; }; 549 } 550 551 template <typename T, typename... Args> 552 inline typename Internal::unique_type<T>::unique_type_single make_unique(Args&&... args) 553 { return unique_ptr<T>(new T(eastl::forward<Args>(args)...)); } 554 555 template <typename T> 556 inline typename Internal::unique_type<T>::unique_type_unbounded_array make_unique(size_t n) 557 { 558 typedef typename eastl::remove_extent<T>::type TBase; 559 return unique_ptr<T>(new TBase[n]); 560 } 561 562 // It's not possible to create a unique_ptr for arrays of a known bound (e.g. int[4] as opposed to int[]). 563 template <typename T, typename... Args> 564 typename Internal::unique_type<T>::unique_type_bounded_array 565 make_unique(Args&&...) = delete; 566 567 568 569 570 /// hash specialization for unique_ptr. 571 /// It simply returns eastl::hash(x.get()). If your unique_ptr pointer type (the return value of unique_ptr<T>::get) is 572 /// a custom type and not a built-in pointer type then you will need to independently define eastl::hash for that type. 573 template <typename T, typename D> 574 struct hash< unique_ptr<T, D> > 575 { 576 size_t operator()(const unique_ptr<T, D>& x) const EA_NOEXCEPT 577 { return eastl::hash<typename unique_ptr<T, D>::pointer>()(x.get()); } 578 }; 579 580 /// swap 581 /// Exchanges the owned pointer beween two unique_ptr objects. 582 /// This non-member version is useful for compatibility of unique_ptr 583 /// objects with the C++ Standard Library and other libraries. 584 template <typename T, typename D> 585 inline void swap(unique_ptr<T, D>& a, unique_ptr<T, D>& b) EA_NOEXCEPT 586 { 587 a.swap(b); 588 } 589 590 591 template <typename T1, typename D1, typename T2, typename D2> 592 inline bool operator==(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 593 { 594 return (a.get() == b.get()); 595 } 596 597 template <typename T1, typename D1, typename T2, typename D2> 598 inline bool operator!=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 599 { 600 return !(a.get() == b.get()); 601 } 602 603 /// Returns which unique_ptr is 'less' than the other. Useful when storing 604 /// sorted containers of unique_ptr objects. 605 template <typename T1, typename D1, typename T2, typename D2> 606 inline bool operator<(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 607 { 608 //typedef typename eastl::unique_ptr<T1, D1>::pointer P1; // We currently need to make these temporary variables, as otherwise clang complains about CPointer being int*&&&. 609 //typedef typename eastl::unique_ptr<T2, D2>::pointer P2; // I think there's something wrong with our common_type type trait implementation. 610 //typedef typename eastl::common_type<P1, P2>::type PCommon; // "in instantiation of function template specialization 'eastl::operator<<int, int>, no known conversion from 'element_type *' (aka 'int *') to 'int *&&&' for 1st argument" 611 //return less<PCommon>()(a.get(), b.get()); // It looks like common_type is making CPointer be (e.g.) int*&& instead of int*, though the problem may be in how less<> deals with that. 612 613 typedef typename eastl::unique_ptr<T1, D1>::pointer P1; 614 typedef typename eastl::unique_ptr<T2, D2>::pointer P2; 615 typedef typename eastl::common_type<P1, P2>::type PCommon; 616 PCommon pT1 = a.get(); 617 PCommon pT2 = b.get(); 618 return less<PCommon>()(pT1, pT2); 619 } 620 621 template <typename T1, typename D1, typename T2, typename D2> 622 inline bool operator>(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 623 { 624 return (b < a); 625 } 626 627 template <typename T1, typename D1, typename T2, typename D2> 628 inline bool operator<=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 629 { 630 return !(b < a); 631 } 632 633 template <typename T1, typename D1, typename T2, typename D2> 634 inline bool operator>=(const unique_ptr<T1, D1>& a, const unique_ptr<T2, D2>& b) 635 { 636 return !(a < b); 637 } 638 639 640 template <typename T, typename D> 641 inline bool operator==(const unique_ptr<T, D>& a, std::nullptr_t) EA_NOEXCEPT 642 { 643 return !a; 644 } 645 646 template <typename T, typename D> 647 inline bool operator==(std::nullptr_t, const unique_ptr<T, D>& a) EA_NOEXCEPT 648 { 649 return !a; 650 } 651 652 template <typename T, typename D> 653 inline bool operator!=(const unique_ptr<T, D>& a, std::nullptr_t) EA_NOEXCEPT 654 { 655 return static_cast<bool>(a); 656 } 657 658 template <typename T, typename D> 659 inline bool operator!=(std::nullptr_t, const unique_ptr<T, D>& a) EA_NOEXCEPT 660 { 661 return static_cast<bool>(a); 662 } 663 664 template <typename T, typename D> 665 inline bool operator<(const unique_ptr<T, D>& a, std::nullptr_t) 666 { 667 typedef typename unique_ptr<T, D>::pointer pointer; 668 return less<pointer>()(a.get(), nullptr); 669 } 670 671 template <typename T, typename D> 672 inline bool operator<(std::nullptr_t, const unique_ptr<T, D>& b) 673 { 674 typedef typename unique_ptr<T, D>::pointer pointer; 675 pointer pT = b.get(); 676 return less<pointer>()(nullptr, pT); 677 } 678 679 template <typename T, typename D> 680 inline bool operator>(const unique_ptr<T, D>& a, std::nullptr_t) 681 { 682 return (nullptr < a); 683 } 684 685 template <typename T, typename D> 686 inline bool operator>(std::nullptr_t, const unique_ptr<T, D>& b) 687 { 688 return (b < nullptr); 689 } 690 691 template <typename T, typename D> 692 inline bool operator<=(const unique_ptr<T, D>& a, std::nullptr_t) 693 { 694 return !(nullptr < a); 695 } 696 697 template <typename T, typename D> 698 inline bool operator<=(std::nullptr_t, const unique_ptr<T, D>& b) 699 { 700 return !(b < nullptr); 701 } 702 703 template <typename T, typename D> 704 inline bool operator>=(const unique_ptr<T, D>& a, std::nullptr_t) 705 { 706 return !(a < nullptr); 707 } 708 709 template <typename T, typename D> 710 inline bool operator>=(std::nullptr_t, const unique_ptr<T, D>& b) 711 { 712 return !(nullptr < b); 713 } 714 715 716 } // namespace eastl 717 718 719 #endif // Header include guard 720 721 722 723 724 725 726 727 728 729 730 731