// ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef SMART_COM_PTR_H #define SMART_COM_PTR_H #include #include namespace util { /* ComPtr: RAII class handling COM objects Example: -------- ComPtr devFinder; if (FAILED(::CoCreateInstance(CLSID_UPnPDeviceFinder, NULL, CLSCTX_ALL, IID_PPV_ARGS(devFinder.init())))) return -1; ComPtr devEnum = com_dynamic_cast(devColl); if (!devEnum) return -1; */ template class ComPtr { public: ComPtr(); ComPtr(const ComPtr& rhs); ComPtr& operator=(const ComPtr& rhs); ~ComPtr(); T** init(); //get pointer for use with ::CoCreateInstance() T* get() const; T* release(); //throw() void swap(ComPtr& rhs); //throw() T* operator->() const; private: T* ptr; struct ConversionToBool { int dummy; }; public: operator int ConversionToBool::*() const; //use member pointer as implicit conversion to bool (C++ Templates - Vandevoorde/Josuttis; chapter 20) }; template ComPtr com_dynamic_cast(const ComPtr& other); //throw() //################# Inline Implementation ############################# template inline ComPtr::ComPtr() : ptr(NULL) {} template inline ComPtr::ComPtr(const ComPtr& rhs) : ptr(rhs.ptr) { if (ptr) ptr->AddRef(); } template inline ComPtr& ComPtr::operator=(const ComPtr& rhs) { ComPtr(rhs).swap(*this); return *this; } template inline ComPtr::~ComPtr() { if (ptr) ptr->Release(); } template inline T** ComPtr::init() //get pointer for use with ::CoCreateInstance() { ComPtr().swap(*this); return &ptr; } template inline T* ComPtr::get() const { return ptr; } template inline T* ComPtr::release() //throw() { T* tmp = ptr; ptr = NULL; return tmp; } template inline void ComPtr::swap(ComPtr& rhs) //throw() { std::swap(ptr, rhs.ptr); } //we cannot specialize std::swap() for a class template and are not allowed to overload it => offer swap in own namespace template inline void swap(util::ComPtr& lhs, util::ComPtr& rhs) { lhs.swap(rhs); } template inline T* ComPtr::operator->() const { return ptr; } /* template inline ComPtr::operator bool() const { return ptr != NULL; } */ template inline ComPtr::operator int ComPtr::ConversionToBool::*() const { return ptr != NULL ? &ConversionToBool::dummy : NULL; } template inline ComPtr com_dynamic_cast(const ComPtr& other) //throw() { ComPtr outPtr; if (other) other->QueryInterface(IID_PPV_ARGS(outPtr.init())); return outPtr; } } #endif //SMART_COM_PTR_H