cm_auto_ptr.hxx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #ifndef CM_AUTO_PTR_HXX
  4. #define CM_AUTO_PTR_HXX
  5. #include <cmConfigure.h>
  6. #ifdef CMake_HAVE_CXX_AUTO_PTR
  7. #include <memory>
  8. #define CM_AUTO_PTR std::auto_ptr
  9. #else
  10. #define CM_AUTO_PTR cm::auto_ptr
  11. // The HP compiler cannot handle the conversions necessary to use
  12. // auto_ptr_ref to pass an auto_ptr returned from one function
  13. // directly to another function as in use_auto_ptr(get_auto_ptr()).
  14. // We instead use const_cast to achieve the syntax on those platforms.
  15. // We do not use const_cast on other platforms to maintain the C++
  16. // standard design and guarantee that if an auto_ptr is bound
  17. // to a reference-to-const then ownership will be maintained.
  18. #if defined(__HP_aCC)
  19. #define cm_AUTO_PTR_REF 0
  20. #define cm_AUTO_PTR_CONST const
  21. #define cm_AUTO_PTR_CAST(a) cast(a)
  22. #else
  23. #define cm_AUTO_PTR_REF 1
  24. #define cm_AUTO_PTR_CONST
  25. #define cm_AUTO_PTR_CAST(a) a
  26. #endif
  27. // In C++11, clang will warn about using dynamic exception specifications
  28. // as they are deprecated. But as this class is trying to faithfully
  29. // mimic std::auto_ptr, we want to keep the 'throw()' decorations below.
  30. // So we suppress the warning.
  31. #if defined(__clang__) && defined(__has_warning)
  32. #if __has_warning("-Wdeprecated")
  33. #pragma clang diagnostic push
  34. #pragma clang diagnostic ignored "-Wdeprecated"
  35. #endif
  36. #endif
  37. namespace cm {
  38. template <class X>
  39. class auto_ptr;
  40. #if cm_AUTO_PTR_REF
  41. namespace detail {
  42. // The auto_ptr_ref template is supposed to be a private member of
  43. // auto_ptr but Borland 5.8 cannot handle it. Instead put it in
  44. // a private namespace.
  45. template <class Y>
  46. struct auto_ptr_ref
  47. {
  48. Y* p_;
  49. // The extra constructor argument prevents implicit conversion to
  50. // auto_ptr_ref from auto_ptr through the constructor. Normally
  51. // this should be done with the explicit keyword but Borland 5.x
  52. // generates code in the conversion operator to call itself
  53. // infinately.
  54. auto_ptr_ref(Y* p, int)
  55. : p_(p)
  56. {
  57. }
  58. };
  59. }
  60. #endif
  61. /** C++98 Standard Section 20.4.5 - Template class auto_ptr. */
  62. template <class X>
  63. class auto_ptr
  64. {
  65. #if !cm_AUTO_PTR_REF
  66. template <typename Y>
  67. static inline auto_ptr<Y>& cast(auto_ptr<Y> const& a)
  68. {
  69. return const_cast<auto_ptr<Y>&>(a);
  70. }
  71. #endif
  72. /** The pointer to the object held. */
  73. X* x_;
  74. public:
  75. /** The type of object held by the auto_ptr. */
  76. typedef X element_type;
  77. /** Construct from an auto_ptr holding a compatible object. This
  78. transfers ownership to the newly constructed auto_ptr. */
  79. template <class Y>
  80. auto_ptr(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw()
  81. : x_(cm_AUTO_PTR_CAST(a).release())
  82. {
  83. }
  84. /** Assign from an auto_ptr holding a compatible object. This
  85. transfers ownership to the left-hand-side of the assignment. */
  86. template <class Y>
  87. auto_ptr& operator=(auto_ptr<Y> cm_AUTO_PTR_CONST& a) throw()
  88. {
  89. this->reset(cm_AUTO_PTR_CAST(a).release());
  90. return *this;
  91. }
  92. /**
  93. * Explicitly construct from a raw pointer. This is typically
  94. * called with the result of operator new. For example:
  95. *
  96. * auto_ptr<X> ptr(new X());
  97. */
  98. explicit auto_ptr(X* p = CM_NULLPTR) throw()
  99. : x_(p)
  100. {
  101. }
  102. /** Construct from another auto_ptr holding an object of the same
  103. type. This transfers ownership to the newly constructed
  104. auto_ptr. */
  105. auto_ptr(auto_ptr cm_AUTO_PTR_CONST& a) throw()
  106. : x_(cm_AUTO_PTR_CAST(a).release())
  107. {
  108. }
  109. /** Assign from another auto_ptr holding an object of the same type.
  110. This transfers ownership to the newly constructed auto_ptr. */
  111. auto_ptr& operator=(auto_ptr cm_AUTO_PTR_CONST& a) throw()
  112. {
  113. this->reset(cm_AUTO_PTR_CAST(a).release());
  114. return *this;
  115. }
  116. /** Destruct and delete the object held. */
  117. ~auto_ptr() throw()
  118. {
  119. // Assume object destructor is nothrow.
  120. delete this->x_;
  121. }
  122. /** Dereference and return a reference to the object held. */
  123. X& operator*() const throw() { return *this->x_; }
  124. /** Return a pointer to the object held. */
  125. X* operator->() const throw() { return this->x_; }
  126. /** Return a pointer to the object held. */
  127. X* get() const throw() { return this->x_; }
  128. /** Return a pointer to the object held and reset to hold no object.
  129. This transfers ownership to the caller. */
  130. X* release() throw()
  131. {
  132. X* x = this->x_;
  133. this->x_ = CM_NULLPTR;
  134. return x;
  135. }
  136. /** Assume ownership of the given object. The object previously
  137. held is deleted. */
  138. void reset(X* p = 0) throw()
  139. {
  140. if (this->x_ != p) {
  141. // Assume object destructor is nothrow.
  142. delete this->x_;
  143. this->x_ = p;
  144. }
  145. }
  146. /** Convert to an auto_ptr holding an object of a compatible type.
  147. This transfers ownership to the returned auto_ptr. */
  148. template <class Y>
  149. operator auto_ptr<Y>() throw()
  150. {
  151. return auto_ptr<Y>(this->release());
  152. }
  153. #if cm_AUTO_PTR_REF
  154. /** Construct from an auto_ptr_ref. This is used when the
  155. constructor argument is a call to a function returning an
  156. auto_ptr. */
  157. auto_ptr(detail::auto_ptr_ref<X> r) throw()
  158. : x_(r.p_)
  159. {
  160. }
  161. /** Assign from an auto_ptr_ref. This is used when a function
  162. returning an auto_ptr is passed on the right-hand-side of an
  163. assignment. */
  164. auto_ptr& operator=(detail::auto_ptr_ref<X> r) throw()
  165. {
  166. this->reset(r.p_);
  167. return *this;
  168. }
  169. /** Convert to an auto_ptr_ref. This is used when a function
  170. returning an auto_ptr is the argument to the constructor of
  171. another auto_ptr. */
  172. template <class Y>
  173. operator detail::auto_ptr_ref<Y>() throw()
  174. {
  175. return detail::auto_ptr_ref<Y>(this->release(), 1);
  176. }
  177. #endif
  178. };
  179. } // namespace cm
  180. // Undo warning suppression.
  181. #if defined(__clang__) && defined(__has_warning)
  182. #if __has_warning("-Wdeprecated")
  183. #pragma clang diagnostic pop
  184. #endif
  185. #endif
  186. #endif
  187. #endif