00001 /* ///////////////////////////////////////////////////////////////////////// 00002 * File: stlsoft/memory/auto_destructor.hpp 00003 * 00004 * Purpose: Contains the auto_destructor and auto_array_destructor template 00005 * classes. 00006 * 00007 * Created: 1st November 1994 00008 * Updated: 10th August 2009 00009 * 00010 * Home: http://stlsoft.org/ 00011 * 00012 * Copyright (c) 1994-2009, Matthew Wilson and Synesis Software 00013 * All rights reserved. 00014 * 00015 * Redistribution and use in source and binary forms, with or without 00016 * modification, are permitted provided that the following conditions are met: 00017 * 00018 * - Redistributions of source code must retain the above copyright notice, this 00019 * list of conditions and the following disclaimer. 00020 * - Redistributions in binary form must reproduce the above copyright notice, 00021 * this list of conditions and the following disclaimer in the documentation 00022 * and/or other materials provided with the distribution. 00023 * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of 00024 * any contributors may be used to endorse or promote products derived from 00025 * this software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 * 00039 * ////////////////////////////////////////////////////////////////////// */ 00040 00041 00049 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR 00050 #define STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR 00051 00052 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION 00053 # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR_MAJOR 5 00054 # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR_MINOR 1 00055 # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR_REVISION 2 00056 # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR_EDIT 72 00057 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ 00058 00059 /* ///////////////////////////////////////////////////////////////////////// 00060 * Compatibility 00061 */ 00062 00063 /* 00064 [DocumentationStatus:Ready] 00065 */ 00066 00067 /* ///////////////////////////////////////////////////////////////////////// 00068 * Includes 00069 */ 00070 00071 #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT 00072 # include <stlsoft/stlsoft.h> 00073 #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */ 00074 00075 #ifdef _STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR 00076 # define STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR 00077 #endif /* _STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR */ 00078 00079 #ifdef _STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT 00080 # define STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT 00081 #endif /* _STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT */ 00082 00083 00084 /* ///////////////////////////////////////////////////////////////////////// 00085 * Warnings 00086 */ 00087 00088 #if defined(STLSOFT_COMPILER_IS_MSVC) && \ 00089 _MSC_VER < 1300 00090 # pragma warning(disable : 4284) 00091 #endif /* compiler */ 00092 00093 /* ///////////////////////////////////////////////////////////////////////// 00094 * Namespace 00095 */ 00096 00097 #ifndef _STLSOFT_NO_NAMESPACE 00098 namespace stlsoft 00099 { 00100 #endif /* _STLSOFT_NO_NAMESPACE */ 00101 00102 /* ///////////////////////////////////////////////////////////////////////// 00103 * Forward declarations 00104 */ 00105 00106 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION 00107 00108 template <ss_typename_param_k T> 00109 class auto_destructor; 00110 00111 template <ss_typename_param_k T> 00112 class return_value_destructor; 00113 00114 template <ss_typename_param_k T> 00115 class auto_array_destructor; 00116 00117 template <ss_typename_param_k T> 00118 class return_value_array_destructor; 00119 00120 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ 00121 00122 /* ///////////////////////////////////////////////////////////////////////// 00123 * Classes 00124 */ 00125 00136 template< ss_typename_param_k T 00137 , ss_typename_param_k U 00138 > 00139 struct move_proxy 00140 { 00141 move_proxy(T *value) 00142 : m_value(value) 00143 {} 00144 00145 T *m_value; 00146 }; 00147 00148 00149 // class auto_destructor 00199 template <ss_typename_param_k T> 00200 class auto_destructor 00201 { 00204 public: 00206 typedef T value_type; 00208 typedef auto_destructor<T> class_type; 00210 typedef return_value_destructor<T> return_value_type; 00211 private: 00213 typedef move_proxy<T, return_value_type> proxy_type; 00215 00218 public: 00220 ss_explicit_k auto_destructor(value_type *t) 00221 : m_value(t) 00222 {} 00223 #if 0 00225 auto_destructor(return_value_type& rhs) 00226 : m_value(rhs.detach()) 00227 {} 00228 #endif /* 0 */ 00230 auto_destructor(proxy_type rhs) 00231 : m_value(rhs.m_value) 00232 {} 00234 ~auto_destructor() stlsoft_throw_0() 00235 { 00236 delete m_value; 00237 } 00239 00242 public: 00246 value_type *detach() 00247 { 00248 value_type *t = m_value; 00249 00250 m_value = 0; 00251 00252 return t; 00253 } 00255 00258 public: 00260 value_type* operator ->() 00261 { 00262 return m_value; 00263 } 00265 value_type const* operator ->() const 00266 { 00267 return m_value; 00268 } 00273 value_type* get_ptr() const 00274 { 00275 return get(); 00276 } 00278 value_type* get() const 00279 { 00280 return m_value; 00281 } 00283 00286 private: 00287 value_type* m_value; 00289 00290 // Not to be implemented 00291 private: 00292 auto_destructor(class_type const& rhs); 00293 auto_destructor const& operator =(class_type const& rhs); 00294 }; 00295 00296 // class auto_array_destructor 00318 template <ss_typename_param_k T> 00319 class auto_array_destructor 00320 { 00323 public: 00325 typedef T value_type; 00327 typedef auto_array_destructor<T> class_type; 00329 typedef return_value_array_destructor<T> return_value_type; 00330 private: 00332 typedef move_proxy<T, return_value_type> proxy_type; 00334 00337 public: 00339 ss_explicit_k auto_array_destructor(value_type t[]) 00340 : m_value(t) 00341 {} 00342 #if 0 00344 auto_array_destructor(return_value_type& rhs) 00345 : m_value(rhs.detach()) 00346 {} 00347 #endif /* 0 */ 00349 auto_array_destructor(proxy_type rhs) 00350 : m_value(rhs.m_value) 00351 {} 00353 ~auto_array_destructor() stlsoft_throw_0() 00354 { 00355 delete [] m_value; 00356 } 00358 00361 public: 00365 value_type *detach() 00366 { 00367 value_type *t = m_value; 00368 00369 m_value = 0; 00370 00371 return t; 00372 } 00374 00377 public: 00379 value_type* operator ->() 00380 { 00381 return m_value; 00382 } 00384 value_type const* operator ->() const 00385 { 00386 return m_value; 00387 } 00392 value_type* get_ptr() const 00393 { 00394 return get(); 00395 } 00397 value_type* get() const 00398 { 00399 return m_value; 00400 } 00402 00405 private: 00406 value_type* m_value; 00408 00409 // Not to be implemented 00410 private: 00411 auto_array_destructor(class_type const& rhs); 00412 auto_array_destructor const& operator =(class_type const& rhs); 00413 }; 00414 00415 00416 // class return_value_destructor 00426 template <ss_typename_param_k T> 00427 class return_value_destructor 00428 { 00431 public: 00433 typedef T value_type; 00435 typedef return_value_destructor<T> class_type; 00437 typedef auto_destructor<T> auto_type; 00438 private: 00440 typedef move_proxy<T, class_type> proxy_type; 00442 00445 public: 00446 #ifdef STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR 00448 return_value_destructor(value_type *pt) 00449 : m_value(pt) 00450 {} 00451 #endif /* STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR */ 00453 return_value_destructor(auto_type& rhs) // Note: not explicit 00454 : m_value(rhs.detach()) 00455 {} 00457 return_value_destructor(class_type& rhs) 00458 : m_value(rhs.detach()) 00459 {} 00461 return_value_destructor(proxy_type rhs) 00462 : m_value(rhs.m_value) 00463 {} 00465 ~return_value_destructor() stlsoft_throw_0() 00466 { 00467 // This fires a report if value is non-zero, which indicates that 00468 // the return value had not been used. This is arguably ok since this 00469 // only ever happens in debug builds (what would be the point in 00470 // including in a release build?), so its violation of the rules on 00471 // no-throw destructors can be forgiven. 00472 00473 #ifndef STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT 00474 # if defined(STLSOFT_COMPILER_IS_WATCOM) 00475 STLSOFT_ASSERT(m_value == 0); 00476 # else /* ? compiler */ 00477 STLSOFT_MESSAGE_ASSERT("This return value was not used", m_value == 0); 00478 # endif /* compiler */ 00479 #endif /* !STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT */ 00480 00481 delete m_value; 00482 } 00484 operator proxy_type() 00485 { 00486 return proxy_type(detach()); 00487 } 00489 00492 private: 00493 friend class auto_destructor<T>; 00494 00498 value_type *detach() 00499 { 00500 value_type *t = m_value; 00501 00502 m_value = 0; 00503 00504 return t; 00505 } 00507 00510 private: 00511 value_type *m_value; 00513 00514 // Not to be implemented 00515 private: 00516 return_value_destructor const& operator =(class_type const& rhs); 00517 }; 00518 00519 // class return_value_array_destructor 00529 template <ss_typename_param_k T> 00530 class return_value_array_destructor 00531 { 00534 public: 00536 typedef T value_type; 00538 typedef return_value_array_destructor<T> class_type; 00540 typedef auto_array_destructor<T> auto_type; 00541 private: 00543 typedef move_proxy<T, class_type> proxy_type; 00545 00548 public: 00549 #ifdef STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR 00551 ss_explicit_k return_value_array_destructor(value_type t[]) 00552 : m_value(t) 00553 {} 00554 #endif /* STLSOFT_RETURN_VALUE_DESTRUCTOR_ENABLE_DIRECT_CTOR */ 00556 return_value_array_destructor(auto_type& rhs) // Note: not explicit 00557 : m_value(rhs.detach()) 00558 {} 00559 #if 1 00561 return_value_array_destructor(class_type& rhs) 00562 : m_value(rhs.detach()) 00563 {} 00564 #endif /* 0 */ 00566 return_value_array_destructor(proxy_type rhs) 00567 : m_value(rhs.m_value) 00568 {} 00570 ~return_value_array_destructor() stlsoft_throw_0() 00571 { 00572 // This fires a report if value is non-zero, which indicates that 00573 // the return value had not been used. This is arguably ok since this 00574 // only ever happens in debug builds (what would be the point in 00575 // including in a release build?), so its violation of the rules on 00576 // no-throw destructors can be forgiven. 00577 00578 #ifndef _STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT 00579 # if defined(STLSOFT_COMPILER_IS_WATCOM) 00580 STLSOFT_ASSERT(m_value == 0); 00581 # else /* ? compiler */ 00582 STLSOFT_MESSAGE_ASSERT("This return value was not used", m_value == 0); 00583 # endif /* compiler */ 00584 #endif /* !_STLSOFT_RETURN_VALUE_DESTRUCTOR_DISABLE_UNUSED_ASSERT */ 00585 00586 delete [] m_value; 00587 } 00589 operator proxy_type() 00590 { 00591 return proxy_type(detach()); 00592 } 00594 00597 private: 00598 friend class auto_array_destructor<T>; 00599 00603 value_type *detach() 00604 { 00605 value_type *t = m_value; 00606 00607 m_value = 0; 00608 00609 return t; 00610 } 00612 00615 private: 00616 value_type *m_value; 00618 00619 // Not to be implemented 00620 private: 00621 return_value_array_destructor const& operator =(class_type const& rhs); 00622 }; 00623 00624 /* ///////////////////////////////////////////////////////////////////////// 00625 * Shims 00626 */ 00627 00631 template <ss_typename_param_k T> 00632 inline T *get_ptr(auto_destructor<T> const& ad) 00633 { 00634 return ad.get(); 00635 } 00636 00640 template <ss_typename_param_k T> 00641 inline T* get_ptr(return_value_destructor<T> const& ad) 00642 { 00643 return ad.get(); 00644 } 00645 00649 template <ss_typename_param_k T> 00650 inline T* get_ptr(auto_array_destructor<T> const& ad) 00651 { 00652 return ad.get(); 00653 } 00654 00658 template <ss_typename_param_k T> 00659 inline T* get_ptr(return_value_array_destructor<T> const& ad) 00660 { 00661 return ad.get(); 00662 } 00663 00664 /* ////////////////////////////////////////////////////////////////////// */ 00665 00666 #ifndef _STLSOFT_NO_NAMESPACE 00667 } // namespace stlsoft 00668 #endif /* _STLSOFT_NO_NAMESPACE */ 00669 00670 /* ///////////////////////////////////////////////////////////////////////// 00671 * Warnings 00672 */ 00673 00674 #if defined(STLSOFT_COMPILER_IS_MSVC) && \ 00675 _MSC_VER < 1300 00676 # pragma warning(default: 4284) 00677 #endif /* compiler */ 00678 00679 /* ////////////////////////////////////////////////////////////////////// */ 00680 00681 #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_DESTRUCTOR */ 00682 00683 /* ///////////////////////////// end of file //////////////////////////// */