00001 #ifndef __SMART_PTR_H__
00002 #define __SMART_PTR_H__
00003
00004 #include <functional>
00005 #include <stdexcept>
00006 #include <cassert>
00007
00008
00009
00010
00012
00014 template<int> struct CompileTimeError;
00015 template<> struct CompileTimeError<true> {};
00016
00018
00019
00020
00021
00022
00023
00025 #define STATIC_CHECK(expr, msg) \
00026 { CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
00027
00029
00030
00031
00032
00033
00034
00035
00037 template <bool flag, typename T, typename U>
00038 struct Select
00039 {
00040 typedef T Result;
00041 };
00042
00043 template <typename T, typename U>
00044 struct Select<false, T, U>
00045 {
00046 typedef U Result;
00047 };
00048
00049
00051
00053 namespace Private
00054 {
00055 template <class T, class U>
00056 struct ConversionHelper
00057 {
00058 typedef char Small;
00059 struct Big { char dummy[2]; };
00060 static Big Test(...);
00061 static Small Test(U);
00062 static T MakeT();
00063 };
00064 }
00065
00066
00068
00069
00071 template <class T>
00072 class DefaultSPStorage
00073 {
00074 public:
00075 typedef T* StoredType;
00076 typedef T* PointerType;
00077 typedef T& ReferenceType;
00078
00079 DefaultSPStorage() : pointee_(Default())
00080 {}
00081
00082
00083
00084 DefaultSPStorage(const DefaultSPStorage&)
00085 {}
00086
00087 template <class U>
00088 DefaultSPStorage(const DefaultSPStorage<U>&)
00089 {}
00090
00091 DefaultSPStorage(const StoredType& p) : pointee_(p) {}
00092
00093 PointerType operator->() const { return pointee_; }
00094
00095 ReferenceType operator*() const { return *pointee_; }
00096
00097 void Swap(DefaultSPStorage& rhs)
00098 { std::swap(pointee_, rhs.pointee_); }
00099
00100
00101 friend inline PointerType GetImpl(const DefaultSPStorage& sp)
00102 { return sp.pointee_; }
00103
00104 friend inline const StoredType& GetImplRef(const DefaultSPStorage& sp)
00105 { return sp.pointee_; }
00106
00107 friend inline StoredType& GetImplRef(DefaultSPStorage& sp)
00108 { return sp.pointee_; }
00109
00110 protected:
00111
00112
00113 void Destroy()
00114 { delete pointee_; }
00115
00116
00117 static StoredType Default()
00118 { return 0; }
00119
00120 private:
00121
00122 StoredType pointee_;
00123 };
00124
00125
00127
00128
00129
00131 template <class P>
00132 class RefCounted
00133 {
00134 public:
00135 RefCounted()
00136 {
00137 pCount_ = new unsigned int;
00138 assert(pCount_);
00139 *pCount_ = 1;
00140 }
00141
00142 RefCounted(const RefCounted& rhs)
00143 : pCount_(rhs.pCount_)
00144 {}
00145
00146
00147 template <typename P1>
00148 RefCounted(const RefCounted<P1>& rhs)
00149 : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
00150 {}
00151
00152 P Clone(const P& val)
00153 {
00154 ++*pCount_;
00155 return val;
00156 }
00157
00158 bool Release(const P&)
00159 {
00160 if (!--*pCount_)
00161 {
00162 delete pCount_;
00163 return true;
00164 }
00165 return false;
00166 }
00167
00168 void Swap(RefCounted& rhs)
00169 { std::swap(pCount_, rhs.pCount_); }
00170
00171 enum { destructiveCopy = false };
00172
00173 private:
00174
00175 unsigned int* pCount_;
00176 };
00177
00178
00180
00181
00182
00184 struct AllowConversion
00185 {
00186 enum { allow = true };
00187
00188 void Swap(AllowConversion&)
00189 {}
00190 };
00191
00192
00194
00195
00196
00197
00199 struct DisallowConversion
00200 {
00201 DisallowConversion()
00202 {}
00203
00204 DisallowConversion(const AllowConversion&)
00205 {}
00206
00207 enum { allow = false };
00208
00209 void Swap(DisallowConversion&)
00210 {}
00211 };
00212
00213
00215
00216
00217
00219 template <class P>
00220 struct NoCheck
00221 {
00222 NoCheck()
00223 {}
00224
00225 template <class P1>
00226 NoCheck(const NoCheck<P1>&)
00227 {}
00228
00229 static void OnDefault(const P&)
00230 {}
00231
00232 static void OnInit(const P&)
00233 {}
00234
00235 static void OnDereference(const P&)
00236 {}
00237
00238 static void Swap(NoCheck&)
00239 {}
00240 };
00241
00242
00244
00245
00246
00248 template <class P>
00249 struct AssertCheck
00250 {
00251 AssertCheck()
00252 {}
00253
00254 template <class P1>
00255 AssertCheck(const AssertCheck<P1>&)
00256 {}
00257
00258 template <class P1>
00259 AssertCheck(const NoCheck<P1>&)
00260 {}
00261
00262 static void OnDefault(const P&)
00263 {}
00264
00265 static void OnInit(const P&)
00266 {}
00267
00268 static void OnDereference(P val)
00269 { assert(val); (void)val; }
00270
00271 static void Swap(AssertCheck&)
00272 {}
00273 };
00274
00275
00277
00278
00279
00280
00282 template <class P>
00283 struct AssertCheckStrict
00284 {
00285 AssertCheckStrict()
00286 {}
00287
00288 template <class U>
00289 AssertCheckStrict(const AssertCheckStrict<U>&)
00290 {}
00291
00292 template <class U>
00293 AssertCheckStrict(const AssertCheck<U>&)
00294 {}
00295
00296 template <class P1>
00297 AssertCheckStrict(const NoCheck<P1>&)
00298 {}
00299
00300 static void OnDefault(P val)
00301 { assert(val); }
00302
00303 static void OnInit(P val)
00304 { assert(val); }
00305
00306 static void OnDereference(P val)
00307 { assert(val); }
00308
00309 static void Swap(AssertCheckStrict&)
00310 {}
00311 };
00312
00313
00315
00316
00318 struct NullPointerException : public std::runtime_error
00319 {
00320 NullPointerException() : std::runtime_error("")
00321 { }
00322 const char* what() const throw()
00323 { return "Null Pointer Exception"; }
00324 };
00325
00326
00328
00329
00330
00332 template <class P>
00333 struct RejectNullStatic
00334 {
00335 RejectNullStatic()
00336 {}
00337
00338 template <class P1>
00339 RejectNullStatic(const RejectNullStatic<P1>&)
00340 {}
00341
00342 template <class P1>
00343 RejectNullStatic(const NoCheck<P1>&)
00344 {}
00345
00346 template <class P1>
00347 RejectNullStatic(const AssertCheck<P1>&)
00348 {}
00349
00350 template <class P1>
00351 RejectNullStatic(const AssertCheckStrict<P1>&)
00352 {}
00353
00354 static void OnDefault(const P&)
00355 {
00356
00357 static const bool DependedFalse = sizeof(P*) == 0;
00358
00359 STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
00360 }
00361
00362 static void OnInit(const P& val)
00363 { if (!val) throw NullPointerException(); }
00364
00365 static void OnDereference(const P& val)
00366 { if (!val) throw NullPointerException(); }
00367
00368 static void Swap(RejectNullStatic&)
00369 {}
00370 };
00371
00372
00374
00375
00376
00378 template <class P>
00379 struct RejectNull
00380 {
00381 RejectNull()
00382 {}
00383
00384 template <class P1>
00385 RejectNull(const RejectNull<P1>&)
00386 {}
00387
00388 static void OnInit(P val)
00389 { if (!val) throw NullPointerException(); }
00390
00391 static void OnDefault(P val)
00392 { OnInit(val); }
00393
00394 void OnDereference(P val)
00395 { OnInit(val); }
00396
00397 void Swap(RejectNull&)
00398 {}
00399 };
00400
00401
00403
00404
00405
00407 template <class P>
00408 struct RejectNullStrict
00409 {
00410 RejectNullStrict()
00411 {}
00412
00413 template <class P1>
00414 RejectNullStrict(const RejectNullStrict<P1>&)
00415 {}
00416
00417 template <class P1>
00418 RejectNullStrict(const RejectNull<P1>&)
00419 {}
00420
00421 static void OnInit(P val)
00422 { if (!val) throw NullPointerException(); }
00423
00424 void OnDereference(P val)
00425 { OnInit(val); }
00426
00427 void Swap(RejectNullStrict&)
00428 {}
00429 };
00430
00431
00433
00434
00435
00437 template <class T>
00438 class ByRef
00439 {
00440 public:
00441 ByRef(T& v) : value_(v) {}
00442 operator T&() { return value_; }
00443
00444
00445 private:
00446 ByRef& operator=(const ByRef &);
00447 T& value_;
00448 };
00449
00450
00452
00453
00455 template
00456 <
00457 typename T,
00458 template <class> class OwnershipPolicy = RefCounted,
00459 class ConversionPolicy = DisallowConversion,
00460 template <class> class CheckingPolicy = AssertCheck,
00461 template <class> class StoragePolicy = DefaultSPStorage
00462 >
00463 class CSmartPtr;
00464
00465
00467
00468
00469
00471 template
00472 <
00473 typename T,
00474 template <class> class OwnershipPolicy = RefCounted,
00475 class ConversionPolicy = DisallowConversion,
00476 template <class> class CheckingPolicy = AssertCheck,
00477 template <class> class StoragePolicy = DefaultSPStorage
00478 >
00479 struct CSmartPtrDef
00480 {
00481 typedef CSmartPtr
00482 <
00483 T,
00484 OwnershipPolicy,
00485 ConversionPolicy,
00486 CheckingPolicy,
00487 StoragePolicy
00488 >
00489 type;
00490 };
00491
00492
00494
00496 template
00497 <
00498 typename T,
00499 template <class> class OwnershipPolicy,
00500 class ConversionPolicy,
00501 template <class> class CheckingPolicy,
00502 template <class> class StoragePolicy
00503 >
00504 class CSmartPtr
00505 : public StoragePolicy<T>
00506 , public OwnershipPolicy<typename StoragePolicy<T>::PointerType>
00507 , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
00508 , public ConversionPolicy
00509 {
00510 typedef StoragePolicy<T> SP;
00511 typedef OwnershipPolicy<typename StoragePolicy<T>::PointerType> OP;
00512 typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
00513 typedef ConversionPolicy CP;
00514
00515 public:
00516 typedef typename SP::PointerType PointerType;
00517 typedef typename SP::StoredType StoredType;
00518 typedef typename SP::ReferenceType ReferenceType;
00519
00520 typedef typename Select<OP::destructiveCopy,
00521 CSmartPtr, const CSmartPtr>::Result
00522 CopyArg;
00523
00524 private:
00525 struct NeverMatched;
00526
00527 #ifdef SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
00528 typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
00529 typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
00530 #else
00531 typedef const StoredType& ImplicitArg;
00532 typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
00533 #endif
00534
00535 public:
00536
00537 CSmartPtr()
00538 { KP::OnDefault(GetImpl(*this)); }
00539
00540 explicit
00541 CSmartPtr(ExplicitArg p) : SP(p)
00542 { KP::OnInit(GetImpl(*this)); }
00543
00544 CSmartPtr(ImplicitArg p) : SP(p)
00545 { KP::OnInit(GetImpl(*this)); }
00546
00547 CSmartPtr(CopyArg& rhs)
00548 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00549 { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00550
00551 template
00552 <
00553 typename T1,
00554 template <class> class OP1,
00555 class CP1,
00556 template <class> class KP1,
00557 template <class> class SP1
00558 >
00559 CSmartPtr(const CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs)
00560 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00561 { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00562
00563 template
00564 <
00565 typename T1,
00566 template <class> class OP1,
00567 class CP1,
00568 template <class> class KP1,
00569 template <class> class SP1
00570 >
00571 CSmartPtr(CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs)
00572 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00573 { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
00574
00575 CSmartPtr(ByRef<CSmartPtr> rhs)
00576 : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
00577 {}
00578
00579 operator ByRef<CSmartPtr>()
00580 { return ByRef<CSmartPtr>(*this); }
00581
00582 CSmartPtr& operator=(CopyArg& rhs)
00583 {
00584 CSmartPtr temp(rhs);
00585 temp.Swap(*this);
00586 return *this;
00587 }
00588
00589 template
00590 <
00591 typename T1,
00592 template <class> class OP1,
00593 class CP1,
00594 template <class> class KP1,
00595 template <class> class SP1
00596 >
00597 CSmartPtr& operator=(const CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs)
00598 {
00599 CSmartPtr temp(rhs);
00600 temp.Swap(*this);
00601 return *this;
00602 }
00603
00604 template
00605 <
00606 typename T1,
00607 template <class> class OP1,
00608 class CP1,
00609 template <class> class KP1,
00610 template <class> class SP1
00611 >
00612 CSmartPtr& operator=(CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs)
00613 {
00614 CSmartPtr temp(rhs);
00615 temp.Swap(*this);
00616 return *this;
00617 }
00618
00619 void Swap(CSmartPtr& rhs)
00620 {
00621 OP::Swap(rhs);
00622 CP::Swap(rhs);
00623 KP::Swap(rhs);
00624 SP::Swap(rhs);
00625 }
00626
00627 ~CSmartPtr()
00628 {
00629 if (OP::Release(GetImpl(*static_cast<SP*>(this))))
00630 {
00631 SP::Destroy();
00632 }
00633 }
00634
00635 friend inline void Release(CSmartPtr& sp, typename SP::StoredType& p)
00636 {
00637 p = GetImplRef(sp);
00638 GetImplRef(sp) = SP::Default();
00639 }
00640
00641 friend inline void Reset(CSmartPtr& sp, typename SP::StoredType p)
00642 { CSmartPtr(p).Swap(sp); }
00643
00644 PointerType operator->()
00645 {
00646 KP::OnDereference(GetImplRef(*this));
00647 return SP::operator->();
00648 }
00649
00650 PointerType operator->() const
00651 {
00652 KP::OnDereference(GetImplRef(*this));
00653 return SP::operator->();
00654 }
00655
00656 ReferenceType operator*()
00657 {
00658 KP::OnDereference(GetImplRef(*this));
00659 return SP::operator*();
00660 }
00661
00662 ReferenceType operator*() const
00663 {
00664 KP::OnDereference(GetImplRef(*this));
00665 return SP::operator*();
00666 }
00667
00668 bool operator!() const
00669 { return GetImpl(*this) == 0; }
00670
00671
00672
00673 template
00674 <
00675 typename T1,
00676 template <class> class OP1,
00677 class CP1,
00678 template <class> class KP1,
00679 template <class> class SP1
00680 >
00681 bool operator==(const CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs) const
00682 { return GetImpl(*this) == GetImpl(rhs); }
00683
00684
00685 template
00686 <
00687 typename T1,
00688 template <class> class OP1,
00689 class CP1,
00690 template <class> class KP1,
00691 template <class> class SP1
00692 >
00693 bool operator!=(const CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs) const
00694 { return !(*this == rhs); }
00695
00696
00697 template
00698 <
00699 typename T1,
00700 template <class> class OP1,
00701 class CP1,
00702 template <class> class KP1,
00703 template <class> class SP1
00704 >
00705 bool operator<(const CSmartPtr<T1, OP1, CP1, KP1, SP1>& rhs) const
00706 { return GetImpl(*this) < GetImpl(rhs); }
00707
00708 private:
00709
00710 struct Tester
00711 {
00712 Tester(int) {}
00713 void dummy() {}
00714 };
00715
00716 typedef void (Tester::*unspecified_boolean_type_)();
00717
00718 typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
00719 unspecified_boolean_type;
00720
00721 public:
00722
00723 operator unspecified_boolean_type() const
00724 {
00725 return !*this ? 0 : &Tester::dummy;
00726 }
00727
00728 private:
00729
00730 struct Insipid
00731 {
00732 Insipid(PointerType) {}
00733 };
00734
00735 typedef typename Select<CP::allow, PointerType, Insipid>::Result
00736 AutomaticConversionResult;
00737
00738 public:
00739 operator AutomaticConversionResult() const
00740 { return GetImpl(*this); }
00741 };
00742
00744
00746
00748
00750 template
00751 <
00752 typename T,
00753 template <class> class OP,
00754 class CP,
00755 template <class> class KP,
00756 template <class> class SP,
00757 typename U
00758 >
00759 inline bool operator==(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00760 U* rhs)
00761 { return GetImpl(lhs) == rhs; }
00762
00763
00765
00767 template
00768 <
00769 typename T,
00770 template <class> class OP,
00771 class CP,
00772 template <class> class KP,
00773 template <class> class SP,
00774 typename U
00775 >
00776 inline bool operator==(U* lhs,
00777 const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00778 { return rhs == lhs; }
00779
00780
00782
00784 template
00785 <
00786 typename T,
00787 template <class> class OP,
00788 class CP,
00789 template <class> class KP,
00790 template <class> class SP,
00791 typename U
00792 >
00793 inline bool operator!=(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00794 U* rhs)
00795 { return !(lhs == rhs); }
00796
00797
00799
00801 template
00802 <
00803 typename T,
00804 template <class> class OP,
00805 class CP,
00806 template <class> class KP,
00807 template <class> class SP,
00808 typename U
00809 >
00810 inline bool operator!=(U* lhs,
00811 const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00812 { return rhs != lhs; }
00813
00814
00816
00818 template
00819 <
00820 typename T,
00821 template <class> class OP,
00822 class CP,
00823 template <class> class KP,
00824 template <class> class SP,
00825 typename U
00826 >
00827 inline bool operator<(const CSmartPtr<T, OP, CP, KP, SP>& lhs, U* rhs)
00828 { return GetImpl(lhs) < rhs; }
00829
00830
00832
00834 template
00835 <
00836 typename T,
00837 template <class> class OP,
00838 class CP,
00839 template <class> class KP,
00840 template <class> class SP,
00841 typename U
00842 >
00843 inline bool operator<(U* lhs, const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00844 { return GetImpl(rhs) < lhs; }
00845
00846
00848
00850 template
00851 <
00852 typename T,
00853 template <class> class OP,
00854 class CP,
00855 template <class> class KP,
00856 template <class> class SP,
00857 typename U
00858 >
00859 inline bool operator>(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00860 U* rhs)
00861 { return rhs < lhs; }
00862
00863
00865
00867 template
00868 <
00869 typename T,
00870 template <class> class OP,
00871 class CP,
00872 template <class> class KP,
00873 template <class> class SP,
00874 typename U
00875 >
00876 inline bool operator>(U* lhs,
00877 const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00878 { return rhs < lhs; }
00879
00880
00882
00884 template
00885 <
00886 typename T,
00887 template <class> class OP,
00888 class CP,
00889 template <class> class KP,
00890 template <class> class SP,
00891 typename U
00892 >
00893 inline bool operator<=(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00894 U* rhs)
00895 { return !(rhs < lhs); }
00896
00897
00899
00901 template
00902 <
00903 typename T,
00904 template <class> class OP,
00905 class CP,
00906 template <class> class KP,
00907 template <class> class SP,
00908 typename U
00909 >
00910 inline bool operator<=(U* lhs,
00911 const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00912 { return !(rhs < lhs); }
00913
00914
00916
00918 template
00919 <
00920 typename T,
00921 template <class> class OP,
00922 class CP,
00923 template <class> class KP,
00924 template <class> class SP,
00925 typename U
00926 >
00927 inline bool operator>=(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00928 U* rhs)
00929 { return !(lhs < rhs); }
00930
00931
00933
00935 template
00936 <
00937 typename T,
00938 template <class> class OP,
00939 class CP,
00940 template <class> class KP,
00941 template <class> class SP,
00942 typename U
00943 >
00944 inline bool operator>=(U* lhs,
00945 const CSmartPtr<T, OP, CP, KP, SP>& rhs)
00946 { return !(lhs < rhs); }
00947
00948
00950
00952 namespace std
00953 {
00954 template
00955 <
00956 typename T,
00957 template <class> class OP,
00958 class CP,
00959 template <class> class KP,
00960 template <class> class SP
00961 >
00962 struct less< CSmartPtr<T, OP, CP, KP, SP> >
00963 : public binary_function<CSmartPtr<T, OP, CP, KP, SP>,
00964 CSmartPtr<T, OP, CP, KP, SP>, bool>
00965 {
00966 bool operator()(const CSmartPtr<T, OP, CP, KP, SP>& lhs,
00967 const CSmartPtr<T, OP, CP, KP, SP>& rhs) const
00968 { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
00969 };
00970 }
00971
00972 #endif //__SMART_PTR_H__