00001 // -*- C++ -*- 00002 00003 //========================================================================== 00004 /** 00005 * @file Value_Ptr.h 00006 * 00007 * $Id: Value_Ptr.h 69669 2005-11-27 12:11:35Z ossama $ 00008 * 00009 * Value_Ptr implementation based on code in Herb Sutter's book "More 00010 * Exceptional C++". 00011 * 00012 * @author Ossama Othman <ossama@dre.vanderbilt.edu> 00013 */ 00014 //========================================================================== 00015 00016 #ifndef ACE_VALUE_PTR_H 00017 #define ACE_VALUE_PTR_H 00018 00019 #include "ace/config-lite.h" 00020 00021 #include <algorithm> 00022 00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00024 00025 namespace ACE 00026 { 00027 /** 00028 * @struct VP_traits 00029 * 00030 * @brief @c Value_Ptr traits template structure. 00031 * 00032 * The @c Value_Ptr template class delegates some operations to this 00033 * template traits structure. 00034 * 00035 * Specialize this trait template if cloning through copy 00036 * construction is not sufficient. For example, to avoid slicing 00037 * when copying an object through a base class pointer, one can 00038 * implement a virtual "clone" method that can be used to 00039 * polymorphically invoke the appropriate cloning operation(s). 00040 * That virtual method would then be invoked by the @c VP_traits<> 00041 * specialization. 00042 */ 00043 template <typename T> 00044 struct VP_traits 00045 { 00046 /// Copy the given object. 00047 static T * clone (T const * p) { return new T (*p); } 00048 }; 00049 00050 /** 00051 * @class Value_Ptr 00052 * 00053 * @brief Smart pointer implementation designed for use as a class 00054 * member. 00055 * 00056 * Using a @c std::auto_ptr<> as a class member is sometimes 00057 * problematic since ownership of memory is transferred when copying 00058 * such members. This @c Value_Ptr class is explicitly designed to 00059 * avoid such problems by performing copies of the underlying object 00060 * rather than transfer ownership. This, for example, allows it to 00061 * be readily used as a member in classes placed inside STL 00062 * containers. 00063 * 00064 * @see Item 31 in "More Exceptional C++" by Herb Sutter. 00065 */ 00066 template <typename T> 00067 class Value_Ptr 00068 { 00069 public: 00070 00071 /// Constructor. 00072 explicit Value_Ptr (T * p = 0) : p_ (p) { } 00073 00074 /// Destructor. 00075 ~Value_Ptr (void) { delete this->p_; } 00076 00077 /// Deference operator. 00078 T & operator* (void) const { return *this->p_; } 00079 00080 /// Pointer operator. 00081 T * operator-> (void) const { return this->p_; } 00082 00083 /// Non-throwing swap operation used to make assignment strongly 00084 /// exception-safe. 00085 /** 00086 * @note As implemented, the swap operation may not work correctly 00087 * for @c auto_ptr<>s, but why would one use an @c 00088 * auto_ptr<> as the template argument for this particular 00089 * template class!? 00090 */ 00091 void swap (Value_Ptr & other) { std::swap (this->p_, other.p_); } 00092 00093 /// Copy constructor. 00094 Value_Ptr (Value_Ptr const & other) 00095 : p_ (create_from (other.p_)) { } 00096 00097 /// Assignment operator. 00098 Value_Ptr & operator= (Value_Ptr const & other) 00099 { 00100 // Strongly exception-safe. 00101 Value_Ptr temp (other); 00102 this->swap (temp); 00103 return *this; 00104 } 00105 00106 #ifndef ACE_LACKS_MEMBER_TEMPLATES 00107 00108 // Compiler can't handle member templates so we lose converting 00109 // copy operations. 00110 00111 /// Converting copy constructor. 00112 template <typename U> 00113 Value_Ptr (Value_Ptr<U> const & other) 00114 : p_ (create_from (other.p_)) { } 00115 00116 /// Converting assignment operator. 00117 template <typename U> 00118 Value_Ptr & operator= (Value_Ptr<U> const & other) 00119 { 00120 // Strongly exception-safe. 00121 Value_Ptr temp (other); 00122 this->swap (temp); 00123 return *this; 00124 } 00125 00126 #endif /* !ACE_LACKS_MEMBER_TEMPLATES */ 00127 00128 private: 00129 00130 #ifndef ACE_LACKS_MEMBER_TEMPLATES 00131 00132 /// Copying method invoked when copy constructing. 00133 template <typename U> 00134 T * create_from (U const * p) const 00135 { 00136 return p ? VP_traits<U>::clone (p) : 0; 00137 } 00138 00139 #else 00140 00141 // Compiler can't handle member templates so we lose converting 00142 // copy operations. 00143 00144 /// Copying method invoked when copy constructing. 00145 T * create_from (T const * p) const 00146 { 00147 return p ? VP_traits<T>::clone (p) : 0; 00148 } 00149 00150 #endif /* !ACE_LACKS_MEMBER_TEMPLATES */ 00151 00152 private: 00153 00154 #ifndef ACE_LACKS_MEMBER_TEMPLATES 00155 template <typename U> friend class Value_Ptr; 00156 #endif /* !ACE_LACKS_MEMBER_TEMPLATES */ 00157 00158 /// Object owned by this @c Value_Ptr. 00159 T * p_; 00160 00161 }; 00162 00163 } 00164 00165 ACE_END_VERSIONED_NAMESPACE_DECL 00166 00167 #endif /* ACE_VALUE_PTR_H */