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