/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ //+--------------------------------------------------------------------------- // // File: scoped_any.h // // Contents: automatic resource management, a-la std::scoped_ptr // // Classes: scoped_any<> and various typedefs // // Functions: get // reset // release // valid // address // //---------------------------------------------------------------------------- #ifndef SCOPED_ANY #define SCOPED_ANY #include #include "smart_any_fwd.h" #pragma warning(push) // 4284 warning for operator-> returning non-pointer; // compiler issues it even if -> is not used for the specific instance #pragma warning(disable: 4284) namespace detail { // friend function definitions go in scoped_any_helper template struct scoped_any_helper; } // wrap a resource to enforce strict ownership and ensure proper cleanup template class scoped_any { // disallow copy and assignment scoped_any( scoped_any const & ); scoped_any & operator=( scoped_any const & ); // disallow comparison of scoped_any's bool operator==( detail::safe_bool ) const; bool operator!=( detail::safe_bool ) const; typedef detail::safe_types safe_types; public: typedef typename detail::holder::type element_type; typedef close_policy close_policy_type; typedef typename safe_types::pointer_type pointer_type; typedef typename safe_types::reference_type reference_type; // Fix-up the invalid_value type on older compilers typedef typename detail::fixup_invalid_value:: template rebind::type invalid_value_type; friend struct detail::scoped_any_helper; // construct from object pointer explicit scoped_any( T t = invalid_value_type() ) : m_t( t ) { } // destroy the object ~scoped_any() { if( valid() ) { close_policy::close( m_t ); } } // return pointer to class object (assume pointer) pointer_type operator->() const { #ifdef SMART_ANY_PTS // You better not be applying operator-> to a handle! static detail::static_assert::value> const cannot_dereference_a_handle; #endif assert( valid() ); return safe_types::to_pointer( m_t ); } // for use when scoped_any appears in a conditional operator detail::safe_bool() const { return valid() ? detail::safe_true : detail::safe_false; } // for use when scoped_any appears in a conditional bool operator!() const { return ! valid(); } #ifdef SMART_ANY_PTS // if this scoped_any is managing an array, we can use operator[] to index it typename detail::deref::type operator[]( int i ) const { static detail::static_assert::value> const cannot_dereference_a_handle; static detail::static_assert::value> const accessed_like_an_array_but_not_deleted_like_an_array; assert( valid() ); return m_t[ i ]; } // unary operator* lets you write code like: // scoped_any pfoo( new foo ); // foo & f = *pfoo; reference_type operator*() const { static detail::static_assert::value> const cannot_dereference_a_handle; assert( valid() ); return safe_types::to_reference( m_t ); } #endif private: bool valid() const { // see if the managed resource is in the invalid state. return m_t != static_cast( invalid_value_type() ); } // the wrapped object element_type m_t; }; namespace detail { // friend function definitions go in scoped_any_helper template struct scoped_any_helper { // return wrapped pointer static T get( scoped_any const & t ) { return t.m_t; } // return wrapped pointer and give up ownership static T release( scoped_any & t ) { // Fix-up the invalid_value type on older compilers typedef typename detail::fixup_invalid_value:: template rebind::type invalid_value_type; T tmpT = t.m_t; t.m_t = static_cast( invalid_value_type() ); return tmpT; } // destroy designated object and store new pointer static void reset( scoped_any & t, T newT ) { if( t.m_t != newT ) { if( t.valid() ) { close_policy::close( t.m_t ); } t.m_t = newT; } } typedef typename scoped_any::element_type element_type; // return the address of the wrapped pointer static element_type* address( scoped_any & t ) { // check to make sure the wrapped object is in the invalid state assert( !t.valid() ); return address_of( t.m_t ); } }; } // return wrapped resource template inline T get( scoped_any const & t ) { return detail::scoped_any_helper::get( t ); } // return true if the scoped_any contains a currently valid resource template inline bool valid( scoped_any const & t ) { return t; } // return wrapped resource and give up ownership template inline T release( scoped_any & t ) { return detail::scoped_any_helper::release( t ); } // destroy designated object and store new resource template inline void reset( scoped_any & t ) { typedef typename detail::fixup_invalid_value:: template rebind::type invalid_value_type; detail::scoped_any_helper::reset( t, invalid_value_type() ); } // destroy designated object and store new resource template inline void reset( scoped_any & t, U newT ) { detail::scoped_any_helper::reset( t, newT ); } // return the address of the wrapped resource // WARNING: this will assert if the value of the resource is // anything other than invalid_value. template inline typename scoped_any::element_type* address( scoped_any & t ) { return detail::scoped_any_helper::address( t ); } #pragma warning(pop) #endif // This causes the scoped_* typedefs to be defined DECLARE_SMART_ANY_TYPEDEFS(scoped) #if defined(_OBJBASE_H_) & !defined(SCOPED_ANY_CO_INIT) # define SCOPED_ANY_CO_INIT typedef scoped_any scoped_co_close; // Helper class for balancing calls to CoInitialize and CoUninitialize struct scoped_co_init { explicit scoped_co_init( DWORD dwCoInit = COINIT_APARTMENTTHREADED ) : m_hr( smart_co_init_helper( dwCoInit ) ) { } HRESULT hresult() const { return get(m_hr); } scoped_co_close const m_hr; }; #endif