1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>~/ntl-11.4.2/doc/SmartPtr.cpp.html</title>
<meta name="Generator" content="Vim/8.0">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="macvim">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; }
body { font-family: monospace; color: #000000; background-color: #ffffff; }
* { font-size: 1em; }
.Constant { color: #ff8c00; }
.Statement { color: #b03060; font-weight: bold; }
.Comment { color: #0000ee; font-style: italic; }
.Type { color: #008b00; font-weight: bold; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">/*</span><span class="Comment">***************************************************************************</span>
<span class="Comment">SmartPtr: a smart pointer class.</span>
<span class="Comment">Synopsis: provides a reference counted smart pointer, similar to shared_ptr</span>
<span class="Comment">in the standard library. It is provided here to minimize reliance</span>
<span class="Comment">on the standard library, especially for older C++ compilers, which may</span>
<span class="Comment">not provide shared_ptr, or it may be in TR1, which gets messy.</span>
<span class="Comment">Examples:</span>
<span class="Comment"> SmartPtr<T> p1; // initialize to null</span>
<span class="Comment"> SmartPtr<T> p1(0); </span>
<span class="Comment"> SmartPtr<T> p2 = 0; // 0/nullptr implicitly converts to SmartPtr<T></span>
<span class="Comment"> SmartPtr<T> p3(p1); // copy constructor</span>
<span class="Comment"> T *rp;</span>
<span class="Comment"> SmartPtr<T> p4(rp); // construct using raw pointer (explicit): better </span>
<span class="Comment"> // to use MakeSmart below</span>
<span class="Comment"> p1 = MakeSmart<T>(...); // build new T object by invoking constructor</span>
<span class="Comment"> // T(...) with pseudo-variadic templates.</span>
<span class="Comment"> // This is safer and more efficient that</span>
<span class="Comment"> // using the raw-pointer constructor</span>
<span class="Comment"> </span>
<span class="Comment"> p1 = p2; // assignment</span>
<span class="Comment"> p1 = 0; // assign null</span>
<span class="Comment"> if (!p1) ... // test for null</span>
<span class="Comment"> if (p1 == 0) ... </span>
<span class="Comment"> if (p1) ... // test for not null ... </span>
<span class="Comment"> if (p1 != 0) ... </span>
<span class="Comment"> if (p1 == p2) ... // test for equality </span>
<span class="Comment"> if (p1 != p2) </span>
<span class="Comment"> *p1 // dereferencing</span>
<span class="Comment"> p1->...</span>
<span class="Comment"> p1.get(); // return the underlying raw pointer...dangerous!</span>
<span class="Comment"> p1.swap(p2); // fast swap</span>
<span class="Comment"> swap(p1, p2);</span>
<span class="Comment">Automatic Conversions:</span>
<span class="Comment">If S is another class, SmartPtr<S> converts to SmartPtr<T> if S* converts to T*</span>
<span class="Comment">(for example, if S is a subclass of T). Similarly, SmartPtr<S> and SmartPtr<T></span>
<span class="Comment">may be compared if S* and T* may be compared.</span>
<span class="Comment">0/nullptr automatically converts to SmartPtr<T>.</span>
<span class="Comment">MakeSmart:</span>
<span class="Comment">One can write SmartPtr<T> p = MakeSmart<T>(x1, ..., xn), and this will create a</span>
<span class="Comment">smart pointer to an object constructed as T(x1, ..., xn). Besides notational</span>
<span class="Comment">convenience, it also reduces the number of memory allocations from 2 to 1, as</span>
<span class="Comment">the data and control block can be allocated in one chunck of memory.</span>
<span class="Comment">In C++11 mode, this is implemented using variadic templates and "perfect</span>
<span class="Comment">forwarding". Otherwise, this is implemented using macros, and there are some</span>
<span class="Comment">limitations: first, the number n of arguments is limited to 9; second, all</span>
<span class="Comment">arguments are pass by const reference, but you can work around this by using</span>
<span class="Comment">the helper function Fwd. For example, if T has a 2-argument constructor where</span>
<span class="Comment">the second must be a non-const reference of some type, and x2 is a variable of</span>
<span class="Comment">that type, you can write MakeSmart<T>(x1, Fwd(x2)), to forward that reference</span>
<span class="Comment">through in a typesafe manner. Note that for compatibility, the Fwd function is</span>
<span class="Comment">also available in C++11 mode, so you can write code that will work in either</span>
<span class="Comment">mode.</span>
<span class="Comment">MakeRaw:</span>
<span class="Comment">One can also write T *p = MakeRaw<T>(x1, ..., xn) to create a </span>
<span class="Comment">raw pointer. This is the same as writing T *p = new T(x1, ..., xn),</span>
<span class="Comment">except that error handling is determined by the NTL_EXCEPTION</span>
<span class="Comment">flag (on => bad_alloc exception is thrown, off => error message</span>
<span class="Comment">and abort).</span>
<span class="Comment">MakeRawArray:</span>
<span class="Comment">Another utility routine: one can write T *p = MakeRawArray<T>(n)</span>
<span class="Comment">to make a plain array of n T objects. Error handling is the same</span>
<span class="Comment">as for MakeRaw.</span>
<span class="Comment">Dynamic casting:</span>
<span class="Comment">I've also supplied a dynamic cast operation for smart pointers.</span>
<span class="Comment"> SmartPtr<Derived> d = MakeSmart<Derived>(); // d points to Derived</span>
<span class="Comment"> SmartPtr<Base> b = d; // implicit upcast: OK</span>
<span class="Comment"> SmartPtr<Derived> d1 = DynamicCast<Derived>(b);</span>
<span class="Comment"> // downcast to a Derived object -- returns null for a bad cast</span>
<span class="Comment">DeleterPolicy:</span>
<span class="Comment">Normally, when the object pointed to a SmartPtr needs to be destroyed, this is</span>
<span class="Comment">done by invoking delete on the raw pointer. The user can override this</span>
<span class="Comment">behavior by specifying a "deleter policy", which is a class P that defines a</span>
<span class="Comment">static member function deleter, which is invoked as P::deleter(p). Such a</span>
<span class="Comment">policy can be attached to a SmartPtr using a specialized constructor (see</span>
<span class="Comment">below).</span>
<span class="Comment">A deleter policy can be useful, for example, in realizing the PIPL</span>
<span class="Comment">pattern, where the class T's definition is not visible. The specified deleter</span>
<span class="Comment">can invoke a free-standing function that itself invokes delete. A deleter</span>
<span class="Comment">policy can also be useful is memory is to be managed using some mechanism other</span>
<span class="Comment">than new/delete.</span>
<span class="Comment">Implementation notes:</span>
<span class="Comment">If NTL is compiled with the NTL_THREADS option, then the reference counting</span>
<span class="Comment">will be thread safe.</span>
<span class="Comment">The SmartPtrControl class heirarchy is used to make sure the right destructor</span>
<span class="Comment">is called when the ref count goes to zero. This can be an issue for forward</span>
<span class="Comment">declared classes and for subclasses. For example, if T is forward declared in</span>
<span class="Comment">a context where the ref count goes to zero, or if the object's actual type is a</span>
<span class="Comment">subclass of T and T's destructor was not declared virtual. The implementation</span>
<span class="Comment">of SmartPtr guarantees correct behavior in these situations.</span>
<span class="Comment">The null tests p, !p, p == 0, are all effected via an implicit conversion from</span>
<span class="Comment">SmartPtr<T> to a funny pointer type (a pointer to a member function, which</span>
<span class="Comment">avoids other, unwanted implicit conversions: this is the so-called "safe bool</span>
<span class="Comment">idiom");</span>
<span class="Comment">Also, there is an implicit conversion from another funny pointer type to</span>
<span class="Comment">SmartPtr<T>, which is how the implicit conversion from 0/nullptr is achieved.</span>
<span class="Comment">In C++11 both of the above effects could perhaps be achieved more directly.</span>
<span class="Comment">The new "explict bool" operator can replace the "safe bool idiom", and </span>
<span class="Comment">the new nullptr_t type could be used to get the conversion from null to work.</span>
<span class="Comment">NOTES: See <a href="http://www.artima.com/cppsource/safebool.html">http://www.artima.com/cppsource/safebool.html</a> for more on the "safe</span>
<span class="Comment">bool idiom". </span>
<span class="Comment">****************************************************************************</span><span class="Comment">*/</span>
<span class="Comment">// The default "deleter policy"</span>
<span class="Type">struct</span> DefaultDeleterPolicy {
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">static</span> <span class="Type">void</span> deleter(T *p) { <span class="Statement">delete</span> p; }
};
<span class="Comment">// A tagging class, for better readability in invoking constructor.</span>
<span class="Comment">// Usage: SmartPtr<T> p(r, ChoosePolicy<MyDeleterPolicy>());</span>
<span class="Type">template</span><<span class="Type">class</span> P>
<span class="Type">struct</span> ChoosePolicy { };
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">class</span> SmartPtr {
<span class="Statement">public</span>:
<span class="Statement">public</span>:
<span class="Type">template</span><<span class="Type">class</span> Y> <span class="Type">explicit</span> SmartPtr(Y* p);
<span class="Comment">// construct smart pointer from raw pointer with deleter policy</span>
<span class="Comment">// DefaultDeleterPolicy (so p should be allocated using new).</span>
<span class="Comment">// NOTE: Y* must convert to T*, but upon the original pointer is preserved</span>
<span class="Comment">// so that when ref count drops to 0, the *original* object of type Y is destroyed.</span>
<span class="Comment">// EXCEPTIONS: a control block is dynamically allocated;</span>
<span class="Comment">// if this allocation fails, the object pointed to by p is destroyed</span>
<span class="Comment">// and a bad_alloc exception is thrown</span>
<span class="Type">template</span><<span class="Type">class</span> Y, <span class="Type">class</span> P> SmartPtr(Y* p, ChoosePolicy<P>);
<span class="Comment">// construct smart pointer from raw pointer with deleter policy P.</span>
<span class="Comment">// NOTE: Y* must convert to T*, but upon the original pointer is preserved</span>
<span class="Comment">// so that when ref count drops to 0, the *original* object of type Y is destroyed.</span>
<span class="Comment">// EXCEPTIONS: a control block is dynamically allocated;</span>
<span class="Comment">// if this allocation fails, the object pointed to by p is destroyed</span>
<span class="Comment">// and a bad_alloc exception is thrown</span>
SmartPtr();
<span class="Comment">// initial value null</span>
SmartPtr(fake_null_type1);
<span class="Comment">// automatic conversion from 0/nullptr</span>
~SmartPtr();
<span class="Comment">// destructor</span>
SmartPtr(<span class="Type">const</span> SmartPtr& other);
SmartPtr& <span class="Statement">operator</span>=(<span class="Type">const</span> SmartPtr& other);
<span class="Comment">// copy and assignment</span>
<span class="Type">template</span><<span class="Type">class</span> Y> SmartPtr(<span class="Type">const</span> SmartPtr<Y>& other);
<span class="Type">template</span><<span class="Type">class</span> Y> SmartPtr& <span class="Statement">operator</span>=(<span class="Type">const</span> SmartPtr<Y>& other);
<span class="Comment">// copy and assignment</span>
SmartPtr(SmartPtr&& other) <span class="Statement">noexcept</span>;
SmartPtr& <span class="Statement">operator</span>=(SmartPtr&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">template</span><<span class="Type">class</span> Y> SmartPtr(SmartPtr<Y>&& other) <span class="Statement">noexcept</span>;
<span class="Type">template</span><<span class="Type">class</span> Y> SmartPtr& <span class="Statement">operator</span>=(SmartPtr<Y>&& other);
<span class="Comment">// move semantics (C++11 only)</span>
T& <span class="Statement">operator</span>*() <span class="Type">const</span>;
T* <span class="Statement">operator</span>->() <span class="Type">const</span>;
<span class="Comment">// indirection</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// get underlying raw pointer</span>
<span class="Type">void</span> swap(SmartPtr& other);
SmartPtr(fake_null_type);
<span class="Comment">// allows assignment and initialization from 0</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparisons to 0</span>
<span class="Type">template</span><<span class="Type">class</span> Y> SmartPtr<Y> DynamicCast() <span class="Type">const</span>;
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(SmartPtr<T>& p, SmartPtr<T>& q);
<span class="Comment">// free dynamic cast function</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y> SmartPtr<X> DynamicCast(<span class="Type">const</span> SmartPtr<Y>& p);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y>
<span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> SmartPtr<X>& a, <span class="Type">const</span> SmartPtr<Y>& b);
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y>
<span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> SmartPtr<X>& a, <span class="Type">const</span> SmartPtr<Y>& b);
<span class="Comment">// MakeSmart variadic template</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span>... Args>
SmartPtr<T> MakeSmart(Args&&... args);
<span class="Comment">// EXCEPTIONS: may throw an exception if constructor for T throws</span>
<span class="Comment">// or memory allocation fails</span>
<span class="Comment">// EXCEPTIONS: unless otherwise specified, the methods above</span>
<span class="Comment">// never throw an exception (under C++11 rules, if a destructor</span>
<span class="Comment">// is invoked that throws an exception, the program will terminate).</span>
<span class="Comment">/*</span><span class="Comment">***************************************************************************</span>
<span class="Comment">Experimantal: CloneablePtr<T> ...essentially same interface as SmartPtr, but </span>
<span class="Comment">allows cloning of complete objects. The differences:</span>
<span class="Comment">* must construct using MakeCloneable</span>
<span class="Comment">* a clone method is provided</span>
<span class="Comment">* implicit conversion from CloneablePtr to SmartPtr is allowed</span>
<span class="Comment">Example:</span>
<span class="Comment"> CloneablePtr<Derived> d = MakeCloneable<Derived>(); </span>
<span class="Comment"> // d points to Derived</span>
<span class="Comment"> CloneablePtr<Base> b = d; // implicit upcast: OK</span>
<span class="Comment"> CloneablePtr<Base> b1 = b.clone(); </span>
<span class="Comment"> // clone of b, which is really a Derived object</span>
<span class="Comment"> CloneablePtr<Derived> d1 = DynamicCast<Derived>(b1);</span>
<span class="Comment"> // downcast to a Derived object -- returns null for a bad cast</span>
<span class="Comment"> SmartPtr<Base> b2 = d1;</span>
<span class="Comment"> </span>
<span class="Comment">Implementation:</span>
<span class="Comment">In the clone method, the object is constructed using the copy constructor for</span>
<span class="Comment">the type T, where T is the compile-time type with which the first smart pointer</span>
<span class="Comment">to this object was was created, even if the pointer has been subsequently</span>
<span class="Comment">upcasted to a base type S. Such objects must have been initially created using</span>
<span class="Comment">the MakeCloneable function. It turns out, this is hard to do in a completely</span>
<span class="Comment">standards-compliant way, because of the type erasure going on. So I settled on</span>
<span class="Comment">the current method, which does some low-level pointer arithmetic. Even with</span>
<span class="Comment">fancy things like multiple and virtual inheritance, it should work, under the</span>
<span class="Comment">assumption that if two objects have the same (runtime) type, then their memory</span>
<span class="Comment">layout is the same. I don't think anything like that is guaranteed by the</span>
<span class="Comment">standard, but this seems reasonable, and it seems to work. Like I said, it is</span>
<span class="Comment">experimental, and I would appreciate feedback from C++ gurus.</span>
<span class="Comment">Note that NTL does not use this feature, but I do have applications where this</span>
<span class="Comment">is convenient.</span>
<span class="Comment">*********************************************************************************</span><span class="Comment">*/</span>
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">class</span> CloneablePtr {
<span class="Statement">public</span>:
CloneablePtr();
<span class="Comment">// initial value null</span>
~CloneablePtr();
<span class="Comment">// if ref count drops to zero, then delete referent</span>
CloneablePtr(<span class="Type">const</span> CloneablePtr& other);
CloneablePtr& <span class="Statement">operator</span>=(<span class="Type">const</span> CloneablePtr& other);
<span class="Comment">// copy and assignment</span>
<span class="Type">template</span><<span class="Type">class</span> Y> CloneablePtr(<span class="Type">const</span> CloneablePtr<Y>& other);
<span class="Type">template</span><<span class="Type">class</span> Y> CloneablePtr& <span class="Statement">operator</span>=(<span class="Type">const</span> CloneablePtr<Y>& other);
<span class="Comment">// copy and assignment</span>
CloneablePtr(CloneablePtr&& other) <span class="Statement">noexcept</span>;
CloneablePtr& <span class="Statement">operator</span>=(CloneablePtr&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">template</span><<span class="Type">class</span> Y> CloneablePtr(CloneablePtr<Y>&& other) <span class="Statement">noexcept</span>;
<span class="Type">template</span><<span class="Type">class</span> Y> CloneablePtr& <span class="Statement">operator</span>=(CloneablePtr<Y>&& other);
<span class="Comment">// move semantics (C++11 only)</span>
T& <span class="Statement">operator</span>*() <span class="Type">const</span>;
T* <span class="Statement">operator</span>->() <span class="Type">const</span>;
<span class="Comment">// indirection</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// get underlying raw pointer</span>
<span class="Type">void</span> swap(CloneablePtr& other);
CloneablePtr(fake_null_type);
<span class="Comment">// allows assignment and initialization from 0</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparisons to 0</span>
<span class="Type">template</span><<span class="Type">class</span> Y> CloneablePtr<Y> DynamicCast() <span class="Type">const</span>;
CloneablePtr clone() <span class="Type">const</span>;
<span class="Comment">// construct a clone, using the copy constructor</span>
<span class="Comment">// EXCEPTIONS: may throw if copy construction fails</span>
<span class="Type">template</span><<span class="Type">class</span> Y> <span class="Statement">operator</span> SmartPtr<Y>();
<span class="Comment">// implicit conversion from CloneablePtr<T> to SmartPtr<Y>,</span>
<span class="Comment">// allowed if T* converts implicitly to Y*.</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(CloneablePtr<T>& p, CloneablePtr<T>& q);
<span class="Comment">// free dynamic cast function</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y> CloneablePtr<X> DynamicCast(<span class="Type">const</span> CloneablePtr<Y>& p);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y>
<span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> CloneablePtr<X>& a, <span class="Type">const</span> CloneablePtr<Y>& b);
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> Y>
<span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> CloneablePtr<X>& a, <span class="Type">const</span> CloneablePtr<Y>& b);
<span class="Comment">// MakeCloneable psuedo-variadic template</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span>... Args>
CloneablePtr<T> MakeCloneable(Args&&... args);
<span class="Comment">// EXCEPTIONS: may throw an exception if constructor for T throws</span>
<span class="Comment">// or memory allocation fails</span>
<span class="Comment">// EXCEPTIONS: unless otherwise specified, the methods above</span>
<span class="Comment">// never throw an exception (under C++11 rules, if a destructor</span>
<span class="Comment">// is invoked that throws an exception, the program will terminate).</span>
<span class="Comment">/*</span><span class="Comment">*********************************************************************</span>
<span class="Comment">UniquePtr<T> -- unique pointer to object with copying disabled.</span>
<span class="Comment">Useful for pointers inside classes so that we can</span>
<span class="Comment">automatically destruct them. </span>
<span class="Comment">Constructors:</span>
<span class="Comment"> UniquePtr<T> p1; // initialize with null</span>
<span class="Comment"> UniquePtr<T> p1(0); </span>
<span class="Comment"> T* rp;</span>
<span class="Comment"> UniquePtr<T> p1(rp); // construct using raw pointer (explicit)</span>
<span class="Comment"> p1 = 0; // destroy's p1's referent and assigns null</span>
<span class="Comment"> p1.make(...); // destroy's p1's referent and assigns</span>
<span class="Comment"> // a fresh objected constructed via T(...),</span>
<span class="Comment"> // using psuedo-variadic templates</span>
<span class="Comment"> </span>
<span class="Comment"> p1.reset(rp); // destroy's p1's referent and assign rp</span>
<span class="Comment"> if (!p1) ... // test for null</span>
<span class="Comment"> if (p1 == 0) ...</span>
<span class="Comment"> if (p1) ... // test for nonnull</span>
<span class="Comment"> if (p1 != 0) ...</span>
<span class="Comment"> if (p1 == p2) ... // test for equality</span>
<span class="Comment"> if (p1 != p2) ... </span>
<span class="Comment"> *p1 // dereferencing</span>
<span class="Comment"> p1->...</span>
<span class="Comment"> rp = p1.get(); // fetch raw pointer</span>
<span class="Comment"> rp = p1.release(); // fetch raw pointer, and set to null</span>
<span class="Comment"> p1.move(p2); // move p2 to p1, destroying p1's referent</span>
<span class="Comment"> // if p1 != p2</span>
<span class="Comment"> p1.swap(p2); // swap pointers</span>
<span class="Comment"> swap(p1, p2);</span>
<span class="Comment">DeleterPolicy:</span>
<span class="Comment">UniquePtr supports a "deleter policy", analogous to that used in SmartPtr.</span>
<span class="Comment">Normally, when the object pointed to a UniquePtr needs to be destroyed, this is</span>
<span class="Comment">done by invoking delete on the raw pointer. The user can override this</span>
<span class="Comment">behavior by specifying a "deleter policy", which is a class P that defines a</span>
<span class="Comment">static member function deleter, which is invoked as P::deleter(p). </span>
<span class="Comment">Unlike with a SmartPtr, the deleter policy must be attached to the type.</span>
<span class="Comment">The default policy is the same DefaultDeleterPolicy, defined above.</span>
<span class="Comment">A deleter policy can be useful, for example, in realizing the PIPL</span>
<span class="Comment">pattern, where the class T's definition is not visible. The specified deleter</span>
<span class="Comment">can invoke a free-standing function that itself invokes delete. A deleter</span>
<span class="Comment">policy can also be useful is memory is to be managed using some mechanism other</span>
<span class="Comment">than new/delete.</span>
<span class="Comment"> </span>
<span class="Comment">*********************************************************************</span><span class="Comment">*/</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span> P=DefaultDeleterPolicy>
<span class="Type">class</span> UniquePtr {
<span class="Statement">public</span>:
<span class="Type">explicit</span> UniquePtr(T *p);
<span class="Comment">// construct UniquePtr from raw pointer (allocated with new)</span>
UniquePtr();
<span class="Comment">// initial value is null</span>
UniquePtr(UniquePtr&& other) <span class="Statement">noexcept</span>;
UniquePtr& <span class="Statement">operator</span>=(UniquePtr&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
UniquePtr& <span class="Statement">operator</span>=(fake_null_type1);
<span class="Comment">// allows assignment of 0; equivalent to calling reset()</span>
~UniquePtr();
<span class="Comment">// destroys referent by calling P::deleter</span>
<span class="Type">void</span> reset(T* p = <span class="Constant">0</span>);
<span class="Comment">// reset underlying pointer to p, destroying original referent</span>
<span class="Comment">// by calling P::deleter</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span>... Args>
<span class="Type">void</span> make(Args&&... args);
<span class="Comment">// pseudo-variadic template, roughly equivalent to</span>
<span class="Comment">// reset(new T(std::forward<args> args...))</span>
<span class="Comment">// EXCEPTIONS: this may throw (but provides strong ES guarantee)</span>
T& <span class="Statement">operator</span>*() <span class="Type">const</span>;
T* <span class="Statement">operator</span>->() <span class="Type">const</span>;
<span class="Comment">// indirection</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// get raw pointer</span>
T* release();
<span class="Comment">// returns raw pointer, and sets the raw pointer to null</span>
<span class="Type">void</span> move(UniquePtr& other);
<span class="Comment">// move other to *this, destroying original referent</span>
<span class="Comment">// by calling P::deleter</span>
<span class="Type">void</span> swap(UniquePtr& other);
<span class="Comment">// swap raw pointers</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparison with 0</span>
<span class="Statement">private</span>:
UniquePtr(<span class="Type">const</span> UniquePtr&); <span class="Comment">// disabled</span>
<span class="Type">void</span> <span class="Statement">operator</span>=(<span class="Type">const</span> UniquePtr&); <span class="Comment">// disabled</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(UniquePtr<T>& p, UniquePtr<T>& q);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> P> <span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> UniquePtr<X,P>& a, <span class="Type">const</span> UniquePtr<X,P>& b);
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> P> <span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> UniquePtr<X,P>& a, <span class="Type">const</span> UniquePtr<X,P>& b);
<span class="Comment">// EXCEPTIONS: unless otherwise specified, the methods above</span>
<span class="Comment">// never throw an exception (under C++11 rules, if a destructor</span>
<span class="Comment">// is invoked that throws an exception, the program will terminate).</span>
<span class="Comment">/*</span><span class="Comment">*********************************************************************</span>
<span class="Comment">CopiedPtr<T> -- essentially the same interface and implemetation as UniquePtr,</span>
<span class="Comment">with the following exceptions:</span>
<span class="Comment"> * copy constructor is defined: by default, it will create a copy</span>
<span class="Comment"> of the referrent using T's copy constructor (but this bahavior</span>
<span class="Comment"> can be overridden -- see below)</span>
<span class="Comment"> * assignment operator is defined (and implemented in terms of the</span>
<span class="Comment"> copy constructor)</span>
<span class="Comment"> * The policy managing a CopiedPtr specifier deleter and copier functions:</span>
<span class="Comment"> the deleter is used to delete objects and the copies is used for making</span>
<span class="Comment"> copies (see below).</span>
<span class="Comment">NOTE: this class is meant to replace the OptionalVal class, whose</span>
<span class="Comment">interface is not so nice. For backwards compatibility, OptionalVal will</span>
<span class="Comment">be maintained, however.</span>
<span class="Comment"> </span>
<span class="Comment">*********************************************************************</span><span class="Comment">*/</span>
<span class="Comment">// This class specifies the default copier</span>
<span class="Type">struct</span> DefaultCopierPolicy {
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">static</span> T* copier(T *p) { <span class="Statement">return</span> (p ? MakeRaw<T>(*p) : <span class="Constant">0</span>); }
};
<span class="Comment">// This class specifies an alternative copier, which is meant</span>
<span class="Comment">// to perform "deep" copies on class heirarchies that support an</span>
<span class="Comment">// appropriate clone() method.</span>
<span class="Type">struct</span> CloningCopier {
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">static</span> T* copier(T *p) { <span class="Statement">return</span> (p ? p->clone() : <span class="Constant">0</span>); }
};
<span class="Type">struct</span> DefaultCopiedPtrPolicy : DefaultDeleterPolicy, DefaultCopierPolicy { };
<span class="Type">struct</span> CloningCopiedPtrPolicy : DefaultDeleterPolicy, CloningCopier { };
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span> P=DefaultCopiedPtrPolicy>
<span class="Type">class</span> CopiedPtr {
<span class="Statement">public</span>:
<span class="Type">explicit</span> CopiedPtr(T *p);
<span class="Comment">// construct CopiedPtr from raw pointer (allocated with new)</span>
CopiedPtr();
<span class="Comment">// initial value is null</span>
CopiedPtr(<span class="Type">const</span> CopiedPtr& other);
<span class="Comment">// creates a copy of other's referent by calling P::copier</span>
<span class="Type">void</span> <span class="Statement">operator</span>=(<span class="Type">const</span> CopiedPtr&);
<span class="Comment">// creates a copy of other's referent by calling P::copier,</span>
<span class="Comment">// and destroys original referent by calling P::deleter</span>
CopiedPtr& <span class="Statement">operator</span>=(fake_null_type1);
<span class="Comment">// allows assignment of 0; equivalent to calling reset()</span>
~CopiedPtr();
<span class="Comment">// destroys referent by calling P::deleter</span>
CopiedPtr(CopiedPtr&& other) <span class="Statement">noexcept</span>;
CopiedPtr& <span class="Statement">operator</span>=(CopiedPtr&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">void</span> reset(T* p = <span class="Constant">0</span>);
<span class="Comment">// reset underlying pointer to p, destroying original referent</span>
<span class="Comment">// by calling P::deleter</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span>... Args>
<span class="Type">void</span> make(Args&&... args);
<span class="Comment">// pseudo-variadic template, roughly equivalent to</span>
<span class="Comment">// reset(new T(std::forward<args> args...))</span>
<span class="Comment">// EXCEPTIONS: this may throw (but provides strong ES guarantee)</span>
T& <span class="Statement">operator</span>*() <span class="Type">const</span>;
T* <span class="Statement">operator</span>->() <span class="Type">const</span>;
<span class="Comment">// indirection</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// get raw pointer</span>
T* release();
<span class="Comment">// returns raw pointer, and sets the raw pointer to null</span>
<span class="Type">void</span> move(CopiedPtr& other);
<span class="Comment">// move other to *this, destroying original referent</span>
<span class="Comment">// by calling P::deleter</span>
<span class="Type">void</span> swap(CopiedPtr& other);
<span class="Comment">// swap raw pointers</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparison with 0</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(CopiedPtr<T>& p, CopiedPtr<T>& q);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> P> <span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> CopiedPtr<X,P>& a, <span class="Type">const</span> CopiedPtr<X,P>& b);
<span class="Type">template</span><<span class="Type">class</span> X, <span class="Type">class</span> P> <span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> CopiedPtr<X,P>& a, <span class="Type">const</span> CopiedPtr<X,P>& b);
<span class="Comment">// EXCEPTIONS: unless otherwise specified, the methods above</span>
<span class="Comment">// never throw an exception (under C++11 rules, if a destructor</span>
<span class="Comment">// is invoked that throws an exception, the program will terminate).</span>
<span class="Comment">/*</span><span class="Comment">*********************************************************************</span>
<span class="Comment">UniqueArray<T> -- similar to UniquePtr, but for arrays. These arrays cannot be</span>
<span class="Comment">resized -- for that, you should use the Vec class.</span>
<span class="Comment">Constructors:</span>
<span class="Comment"> UniqueArray<T> p1; // initialize with null</span>
<span class="Comment"> UniqueArray<T> p1(0); </span>
<span class="Comment"> T* rp;</span>
<span class="Comment"> UniqueArray<T> p1(rp); // construct using raw pointer (explicit)</span>
<span class="Comment"> p1 = 0; // destroy's p1's referent and assigns null</span>
<span class="Comment"> p1.SetLength(n); // destroy's p1's referent and assigns</span>
<span class="Comment"> // a fresh objected constructed via new T[n]</span>
<span class="Comment"> </span>
<span class="Comment"> p1.reset(rp); // destroy's p1's referent and assign rp</span>
<span class="Comment"> if (!p1) ... // test for null</span>
<span class="Comment"> if (p1 == 0) ...</span>
<span class="Comment"> if (p1) ... // test for nonnull</span>
<span class="Comment"> if (p1 != 0) ...</span>
<span class="Comment"> if (p1 == p2) ... // test for equality</span>
<span class="Comment"> if (p1 != p2) ... </span>
<span class="Comment"> p1[i] // array indexing</span>
<span class="Comment"> rp = p1.get(); // fetch raw pointer</span>
<span class="Comment"> rp = p1.release(); // fetch raw pointer, and set to null</span>
<span class="Comment"> p1.move(p2); // move p2 to p1, destroying p1's referent </span>
<span class="Comment"> // if p1 != p2</span>
<span class="Comment"> p1.swap(p2); // fast swap</span>
<span class="Comment"> swap(p1, p2);</span>
<span class="Comment"> </span>
<span class="Comment">*********************************************************************</span><span class="Comment">*/</span>
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">class</span> UniqueArray {
<span class="Statement">public</span>:
<span class="Type">explicit</span> UniqueArray(T *p);
<span class="Comment">// construct from raw pointer (allocated with new[])</span>
UniqueArray();
<span class="Comment">// initially null</span>
UniqueArray& <span class="Statement">operator</span>=(fake_null_type1);
<span class="Comment">// allows of 0</span>
~UniqueArray();
UniqueArray(UniqueArray&& other) <span class="Statement">noexcept</span>;
UniqueArray& <span class="Statement">operator</span>=(UniqueArray&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">void</span> reset(T* p = <span class="Constant">0</span>);
<span class="Comment">// reset with raw pointer, destroying referent</span>
<span class="Type">void</span> SetLength(<span class="Type">long</span> n);
<span class="Comment">// destroys referent and allocates an array of size n</span>
<span class="Comment">// EXCEPTIONS: this may throw (but provides strong ES guarantee)</span>
T& <span class="Statement">operator</span>[](<span class="Type">long</span> i) <span class="Type">const</span>;
<span class="Comment">// accesses ith element in the array (currently no range checking)</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// get raw pointer</span>
T* elts() <span class="Type">const</span>;
<span class="Comment">// get raw pointer (for compatibility with the Vec class)</span>
T* release();
<span class="Comment">// get raw pointer and reset to null</span>
<span class="Type">void</span> move(UniqueArray& other);
<span class="Comment">// move raw pointer</span>
<span class="Type">void</span> swap(UniqueArray& other);
<span class="Comment">// swap raw pointer</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparison to 0</span>
<span class="Statement">private</span>:
UniqueArray(<span class="Type">const</span> UniqueArray&); <span class="Comment">// disabled</span>
<span class="Type">void</span> <span class="Statement">operator</span>=(<span class="Type">const</span> UniqueArray&); <span class="Comment">// disabled</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(UniqueArray<T>& p, UniqueArray<T>& q);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X> <span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> UniqueArray<X>& a, <span class="Type">const</span> UniqueArray<X>& b);
<span class="Type">template</span><<span class="Type">class</span> X> <span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> UniqueArray<X>& a, <span class="Type">const</span> UniqueArray<X>& b);
<span class="Comment">/*</span><span class="Comment">*********************************************************************</span>
<span class="Comment">Unique2DArray<T> -- unique pointer to array of arrays.</span>
<span class="Comment">This is very similar to UniqueArray< UniqueArray<T> >, except that </span>
<span class="Comment">we can retrofit old code that accepts objects of type T**.</span>
<span class="Comment">Constructors:</span>
<span class="Comment"> Unique2DArray<T> p1; // initialize with null</span>
<span class="Comment"> Unique2DArray<T> p1(0); </span>
<span class="Comment"> p1 = 0; // destroy's p1's referent and assigns null</span>
<span class="Comment"> p1.reset();</span>
<span class="Comment"> p1.SetLength(n); // destroy's p1's referent and assigns</span>
<span class="Comment"> // a fresh array of null pointers</span>
<span class="Comment"> p1.SetDims(n, m) // creates an n x m array</span>
<span class="Comment"> </span>
<span class="Comment"> if (!p1) ... // test for null</span>
<span class="Comment"> if (p1 == 0) ...</span>
<span class="Comment"> if (p1) ... // test for nonnull</span>
<span class="Comment"> if (p1 != 0) ...</span>
<span class="Comment"> if (p1 == p2) ... // test for equality</span>
<span class="Comment"> if (p1 != p2) ... </span>
<span class="Comment"> p1[i] // array indexing</span>
<span class="Comment"> T **rp;</span>
<span class="Comment"> rp = p1.get(); // fetch raw pointer</span>
<span class="Comment"> rp = p1.release(); // fetch raw pointer, and set to null</span>
<span class="Comment"> p1.move(p2); // if p1 != p2 then:</span>
<span class="Comment"> // makes p1 point to p2's referent,</span>
<span class="Comment"> // setting p2 to null and destroying</span>
<span class="Comment"> // p1's referent</span>
<span class="Comment"> p1.swap(p2); // fast swap</span>
<span class="Comment"> swap(p1, p2);</span>
<span class="Comment"> </span>
<span class="Comment">*********************************************************************</span><span class="Comment">*/</span>
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">class</span> Unique2DArray {
<span class="Statement">public</span>:
<span class="Type">typedef</span> T *T_ptr;
Unique2DArray();
<span class="Comment">// initially null</span>
Unique2DArray& <span class="Statement">operator</span>=(fake_null_type1);
<span class="Comment">// allows initialization and assignment of 0</span>
~Unique2DArray();
<span class="Comment">// destroys the entire array and each row in the array</span>
Unique2DArray(Unique2DArray&& other) <span class="Statement">noexcept</span>;
Unique2DArray& <span class="Statement">operator</span>=(Unique2DArray&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">void</span> reset();
<span class="Comment">// reset to null</span>
<span class="Type">void</span> SetLength(<span class="Type">long</span> n);
<span class="Comment">// resets the array to a vector of length n,</span>
<span class="Comment">// each entry initialized to null.</span>
<span class="Comment">// EXCEPTIONS: may throw (provides strong ES guarantee)</span>
<span class="Type">void</span> SetDims(<span class="Type">long</span> n, <span class="Type">long</span> m);
<span class="Comment">// resets the array to a 2D array with n rows and m columns.</span>
<span class="Comment">// EXCEPTIONS: may throw (provides strong ES guarantee)</span>
<span class="Type">void</span> SetDimsFrom1(<span class="Type">long</span> n, <span class="Type">long</span> m);
<span class="Comment">// same as above, but only initializes rows 1..n-1.</span>
<span class="Comment">// this helps with some legacy code.</span>
<span class="Comment">// EXCEPTIONS: may throw (provides strong ES guarantee)</span>
T_ptr& <span class="Statement">operator</span>[](<span class="Type">long</span> i) <span class="Type">const</span>;
<span class="Comment">// array indexing, no range checking</span>
T_ptr* get() <span class="Type">const</span>;
<span class="Comment">// return underlying pointer</span>
T_ptr* release() { len = <span class="Constant">0</span>; <span class="Statement">return</span> dp.release(); }
<span class="Comment">// return underlying pointer and reset to null</span>
<span class="Type">void</span> move(Unique2DArray& other);
<span class="Comment">// move pointers</span>
<span class="Type">void</span> swap(Unique2DArray& other);
<span class="Comment">// swap pointers</span>
<span class="Statement">operator</span> fake_null_type() <span class="Type">const</span>;
<span class="Comment">// allows comparison to 0</span>
<span class="Statement">private</span>:
Unique2DArray(<span class="Type">const</span> Unique2DArray&); <span class="Comment">// disabled</span>
<span class="Type">void</span> <span class="Statement">operator</span>=(<span class="Type">const</span> Unique2DArray&); <span class="Comment">// disabled</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(Unique2DArray<T>& p, Unique2DArray<T>& q);
<span class="Comment">// Equality testing</span>
<span class="Type">template</span><<span class="Type">class</span> X> <span class="Type">bool</span> <span class="Statement">operator</span>==(<span class="Type">const</span> Unique2DArray<X>& a, <span class="Type">const</span> Unique2DArray<X>& b);
<span class="Type">template</span><<span class="Type">class</span> X> <span class="Type">bool</span> <span class="Statement">operator</span>!=(<span class="Type">const</span> Unique2DArray<X>& a, <span class="Type">const</span> Unique2DArray<X>& b);
<span class="Comment">/*</span><span class="Comment">*********************************************************************</span>
<span class="Comment">OptionalVal<T> -- unique pointer to object with copying enabled.</span>
<span class="Comment">NOTE: this class is deprecated; use CopiedPtr instead.</span>
<span class="Comment">It will, however, be maintained indefinitely for backward compatibility.</span>
<span class="Comment">Constructors:</span>
<span class="Comment"> OptionalVal<T> p1; // initialize with null</span>
<span class="Comment"> T* rp;</span>
<span class="Comment"> OptionalVal<T> p1(rp); // construct using raw pointer (explicit)</span>
<span class="Comment"> OptionalVal<T> p2(p1); // construct a copy of p1's referent</span>
<span class="Comment"> </span>
<span class="Comment"> p1.make(...); // destroy's p1's referent and assigns</span>
<span class="Comment"> // a fresh objected constructed via T(...),</span>
<span class="Comment"> // using psuedo variadic templates</span>
<span class="Comment"> </span>
<span class="Comment"> p1.reset(rp); // destroy's p1's referent and assign rp</span>
<span class="Comment"> if (p1.exists()) ... // test for null</span>
<span class="Comment"> p1.val() // dereference</span>
<span class="Comment"> rp = p1.get(); // fetch raw pointer</span>
<span class="Comment"> rp = p1.release(); // fetch raw pointer, and set to NULL</span>
<span class="Comment"> p1.move(p2); // move p2 to p1, destroying p1's referent</span>
<span class="Comment"> // if p1 != p2</span>
<span class="Comment"> p1 = p2; // deep copy, using T's copy constructor</span>
<span class="Comment"> p1.swap(p2); // swap pointers</span>
<span class="Comment"> swap(p1, p2);</span>
<span class="Comment"> </span>
<span class="Comment">*********************************************************************</span><span class="Comment">*/</span>
<span class="Type">template</span><<span class="Type">class</span> T>
<span class="Type">class</span> OptionalVal {
<span class="Statement">public</span>:
<span class="Type">explicit</span> OptionalVal(T *p);
<span class="Comment">// initialize using raw pointer (allocated with new)</span>
OptionalVal();
<span class="Comment">// initialize to null</span>
OptionalVal(<span class="Type">const</span> OptionalVal& other);
<span class="Comment">// initialize using a deep copy (via T's copy constructor)</span>
OptionalVal& <span class="Statement">operator</span>=(<span class="Type">const</span> OptionalVal& other);
<span class="Comment">// assignment using a deep copy (via T's copy constructor)</span>
~OptionalVal();
<span class="Comment">// destroys the referent</span>
OptionalVal(OptionalVal&& other) <span class="Statement">noexcept</span>;
OptionalVal& <span class="Statement">operator</span>=(OptionalVal&& other) <span class="Statement">noexcept</span>;
<span class="Comment">// move semantics (C++11 only)</span>
<span class="Type">void</span> reset(T* p = <span class="Constant">0</span>);
<span class="Comment">// resets the referent</span>
<span class="Type">template</span><<span class="Type">class</span> T, <span class="Type">class</span>... Args>
<span class="Type">void</span> make(Args&&... args);
<span class="Comment">// pseudo-variadic template.</span>
<span class="Comment">// resets the referent to a new object T(std::forward<Args> args...)</span>
<span class="Comment">// EXCEPTIONS: may throw an exception (but provides strong ES guarantee)</span>
T& val() <span class="Type">const</span>;
<span class="Comment">// returns reference to referent </span>
<span class="Comment">// if underlying pointer p is null, the indirection *p</span>
<span class="Comment">// is undefined behavior, but most likely leads to program termination</span>
<span class="Type">bool</span> exists() <span class="Type">const</span>;
<span class="Comment">// checks that underlying pointer is not null</span>
T* get() <span class="Type">const</span>;
<span class="Comment">// returns underlying raw pointer</span>
T* release();
<span class="Comment">// returns raw pointer, and sets the raw pointer to null</span>
<span class="Type">void</span> move(OptionalVal& other);
<span class="Comment">// performs a (shallow) pointer move</span>
<span class="Type">void</span> swap(OptionalVal& other);
<span class="Comment">// performs a (shallow) pointer swap</span>
};
<span class="Comment">// free swap function</span>
<span class="Type">template</span><<span class="Type">class</span> T> <span class="Type">void</span> swap(OptionalVal<T>& p, OptionalVal<T>& q);
<span class="Comment">// EXCEPTIONS: unless otherwise specified, the methods above</span>
<span class="Comment">// never throw an exception (under C++11 rules, if a destructor</span>
<span class="Comment">// is invoked that throws an exception, the program will terminate).</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|