/third_party/smartany/auto_any.h

https://github.com/Crystalnix/bitpop-omaha · C Header · 315 lines · 207 code · 45 blank · 63 comment · 5 complexity · 600b2afc195dffec9b04bdd611006d93 MD5 · raw file

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Copyright ( C ) Microsoft, 2002.
  4. //
  5. // File: auto_any.h
  6. //
  7. // Contents: automatic resource management, a-la std::auto_ptr
  8. //
  9. // Classes: auto_any<> and various typedefs
  10. //
  11. // Functions: get
  12. // reset
  13. // release
  14. // valid
  15. // address
  16. //
  17. // Author: Eric Niebler ( ericne@microsoft.com )
  18. //
  19. //----------------------------------------------------------------------------
  20. #ifndef AUTO_ANY
  21. #define AUTO_ANY
  22. #include <cassert>
  23. #include "smart_any_fwd.h"
  24. #pragma warning(push)
  25. // 4284 warning for operator-> returning non-pointer;
  26. // compiler issues it even if -> is not used for the specific instance
  27. #pragma warning(disable: 4284)
  28. namespace detail
  29. {
  30. // friend function definitions go in auto_any_helper
  31. template<typename T,class close_policy,class invalid_value,int unique>
  32. struct auto_any_helper;
  33. }
  34. // proxy reference for auto_any copying
  35. template<typename T,class close_policy,class invalid_value,int unique>
  36. struct auto_any_ref
  37. {
  38. // construct from compatible auto_any
  39. auto_any_ref( auto_any<T,close_policy,invalid_value,unique> & that )
  40. : m_that( that )
  41. {
  42. }
  43. // reference to constructor argument
  44. auto_any<T,close_policy,invalid_value,unique> & m_that;
  45. private:
  46. auto_any_ref * operator=( auto_any_ref const & );
  47. };
  48. // wrap a resource to enforce strict ownership and ensure proper cleanup
  49. template<typename T,class close_policy,class invalid_value,int unique>
  50. class auto_any
  51. {
  52. typedef detail::safe_types<T,close_policy> safe_types;
  53. // disallow comparison of auto_any's
  54. bool operator==( detail::safe_bool ) const;
  55. bool operator!=( detail::safe_bool ) const;
  56. public:
  57. typedef typename detail::holder<T>::type element_type;
  58. typedef close_policy close_policy_type;
  59. typedef typename safe_types::pointer_type pointer_type;
  60. typedef typename safe_types::reference_type reference_type;
  61. // Fix-up the invalid_value type on older compilers
  62. typedef typename detail::fixup_invalid_value<invalid_value>::
  63. template rebind<T>::type invalid_value_type;
  64. friend struct detail::auto_any_helper<T,close_policy,invalid_value,unique>;
  65. // construct from object pointer
  66. explicit auto_any( T t = invalid_value_type() )
  67. : m_t( t )
  68. {
  69. }
  70. // construct by assuming pointer from right auto_any
  71. auto_any( auto_any<T,close_policy,invalid_value,unique> & right )
  72. : m_t( release( right ) )
  73. {
  74. }
  75. // construct by assuming pointer from right auto_any_ref
  76. auto_any( auto_any_ref<T,close_policy,invalid_value,unique> right )
  77. : m_t( release( right.m_that ) )
  78. {
  79. }
  80. // convert to compatible auto_any_ref
  81. operator auto_any_ref<T,close_policy,invalid_value,unique>()
  82. {
  83. return auto_any_ref<T,close_policy,invalid_value,unique>( *this );
  84. }
  85. // assign compatible right
  86. auto_any<T,close_policy,invalid_value,unique> & operator=(
  87. auto_any<T,close_policy,invalid_value,unique> & right )
  88. {
  89. reset( *this, release( right ) );
  90. return *this;
  91. }
  92. // assign compatible right.ref
  93. auto_any<T,close_policy,invalid_value,unique> & operator=(
  94. auto_any_ref<T,close_policy,invalid_value,unique> & right )
  95. {
  96. reset( *this, release( right.m_that ) );
  97. return *this;
  98. }
  99. // destroy the object
  100. ~auto_any()
  101. {
  102. if( valid() )
  103. {
  104. close_policy::close( m_t );
  105. }
  106. }
  107. // return pointer to class object (assume pointer)
  108. pointer_type operator->() const
  109. {
  110. #ifdef SMART_ANY_PTS
  111. // You better not be applying operator-> to a handle!
  112. static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
  113. #endif
  114. assert( valid() );
  115. return safe_types::to_pointer( m_t );
  116. }
  117. // for use when auto_any appears in a conditional
  118. operator detail::safe_bool() const
  119. {
  120. return valid() ? detail::safe_true : detail::safe_false;
  121. }
  122. // for use when auto_any appears in a conditional
  123. bool operator!() const
  124. {
  125. return ! valid();
  126. }
  127. #ifdef SMART_ANY_PTS
  128. // if this auto_any is managing an array, we can use operator[] to index it
  129. typename detail::deref<T>::type operator[]( int i ) const
  130. {
  131. static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
  132. static detail::static_assert<!detail::is_delete<close_policy>::value> const accessed_like_an_array_but_not_deleted_like_an_array;
  133. assert( valid() );
  134. return m_t[ i ];
  135. }
  136. // unary operator* lets you write code like:
  137. // auto_any<foo*,close_delete> pfoo( new foo );
  138. // foo & f = *pfoo;
  139. reference_type operator*() const
  140. {
  141. static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
  142. assert( valid() );
  143. return safe_types::to_reference( m_t );
  144. }
  145. #endif
  146. private:
  147. bool valid() const
  148. {
  149. // see if the managed resource is in the invalid state.
  150. return m_t != static_cast<T>( invalid_value_type() );
  151. }
  152. // the wrapped object
  153. element_type m_t;
  154. };
  155. namespace detail
  156. {
  157. // friend function definitions go in auto_any_helper
  158. template<typename T,class close_policy,class invalid_value,int unique>
  159. struct auto_any_helper
  160. {
  161. // return wrapped pointer
  162. static T get( auto_any<T,close_policy,invalid_value,unique> const & t )
  163. {
  164. return t.m_t;
  165. }
  166. // return wrapped pointer and give up ownership
  167. static T release( auto_any<T,close_policy,invalid_value,unique> & t )
  168. {
  169. // Fix-up the invalid_value type on older compilers
  170. typedef typename detail::fixup_invalid_value<invalid_value>::
  171. template rebind<T>::type invalid_value_type;
  172. T tmpT = t.m_t;
  173. t.m_t = static_cast<T>( invalid_value_type() );
  174. return tmpT;
  175. }
  176. // destroy designated object and store new pointer
  177. static void reset( auto_any<T,close_policy,invalid_value,unique> & t, T newT )
  178. {
  179. if( t.m_t != newT )
  180. {
  181. if( t.valid() )
  182. {
  183. close_policy::close( t.m_t );
  184. }
  185. t.m_t = newT;
  186. }
  187. }
  188. typedef typename auto_any<T,close_policy,invalid_value,unique>::element_type element_type;
  189. // return the address of the wrapped pointer
  190. static element_type* address( auto_any<T,close_policy,invalid_value,unique> & t )
  191. {
  192. // check to make sure the wrapped object is in the invalid state
  193. assert( !t.valid() );
  194. return address_of( t.m_t );
  195. }
  196. };
  197. }
  198. // return wrapped resource
  199. template<typename T,class close_policy,class invalid_value,int unique>
  200. inline T get( auto_any<T,close_policy,invalid_value,unique> const & t )
  201. {
  202. return detail::auto_any_helper<T,close_policy,invalid_value,unique>::get( t );
  203. }
  204. // return true if the auto_any contains a currently valid resource
  205. template<typename T,class close_policy,class invalid_value,int unique>
  206. inline bool valid( auto_any<T,close_policy,invalid_value,unique> const & t )
  207. {
  208. return t;
  209. }
  210. // return wrapped resource and give up ownership
  211. template<typename T,class close_policy,class invalid_value,int unique>
  212. inline T release( auto_any<T,close_policy,invalid_value,unique> & t )
  213. {
  214. return detail::auto_any_helper<T,close_policy,invalid_value,unique>::release( t );
  215. }
  216. // destroy designated object and store new resource
  217. template<typename T,class close_policy,class invalid_value,int unique>
  218. inline void reset( auto_any<T,close_policy,invalid_value,unique> & t )
  219. {
  220. typedef typename detail::fixup_invalid_value<invalid_value>::
  221. template rebind<T>::type invalid_value_type;
  222. detail::auto_any_helper<T,close_policy,invalid_value,unique>::reset( t, invalid_value_type() );
  223. }
  224. // destroy designated object and store new resource
  225. template<typename T,class close_policy,class invalid_value,int unique,typename U>
  226. inline void reset( auto_any<T,close_policy,invalid_value,unique> & t, U newT )
  227. {
  228. detail::auto_any_helper<T,close_policy,invalid_value,unique>::reset( t, newT );
  229. }
  230. // swap the contents of two shared_any objects
  231. template<typename T,class close_policy,class invalid_value,int unique>
  232. void swap( auto_any<T,close_policy,invalid_value,unique> & left,
  233. auto_any<T,close_policy,invalid_value,unique> & right )
  234. {
  235. auto_any<T,close_policy,invalid_value,unique> tmp( left );
  236. left = right;
  237. right = tmp;
  238. }
  239. // return the address of the wrapped resource
  240. // WARNING: this will assert if the value of the resource is
  241. // anything other than invalid_value.
  242. template<typename T,class close_policy,class invalid_value,int unique>
  243. inline typename auto_any<T,close_policy,invalid_value,unique>::element_type*
  244. address( auto_any<T,close_policy,invalid_value,unique> & t )
  245. {
  246. return detail::auto_any_helper<T,close_policy,invalid_value,unique>::address( t );
  247. }
  248. #pragma warning(pop)
  249. #endif
  250. // This causes the auto_* typedefs to be defined
  251. DECLARE_SMART_ANY_TYPEDEFS(auto)
  252. #if defined(_OBJBASE_H_) & !defined(AUTO_ANY_CO_INIT)
  253. # define AUTO_ANY_CO_INIT
  254. typedef auto_any<HRESULT,close_co,co_not_init> auto_co_close;
  255. // Helper class for balancing calls to CoInitialize and CoUninitialize
  256. struct auto_co_init
  257. {
  258. explicit auto_co_init( DWORD dwCoInit = COINIT_APARTMENTTHREADED )
  259. : m_hr( smart_co_init_helper( dwCoInit ) )
  260. {
  261. }
  262. HRESULT hresult() const
  263. {
  264. return get(m_hr);
  265. }
  266. auto_co_close const m_hr;
  267. private:
  268. auto_co_init & operator=( auto_co_init const & );
  269. };
  270. #endif