// ************************************************************************** // * 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 zen { /* 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() : ptr(NULL) {} ComPtr(const ComPtr& other) : ptr(other.ptr) { if (ptr) ptr->AddRef(); } ComPtr( ComPtr&& other) : ptr(other.release()) {} ComPtr& operator=(const ComPtr& other) { ComPtr(other).swap(*this); return *this; } ComPtr& operator=( ComPtr&& other) { swap(other); return *this; } ~ComPtr() { if (ptr) ptr->Release(); } T** init() //get pointer for use with ::CoCreateInstance() { ComPtr().swap(*this); return &ptr; } T* get() const { return ptr; } T* release() //throw() { T* tmp = ptr; ptr = NULL; return tmp; } void swap(ComPtr& rhs) { std::swap(ptr, rhs.ptr); } //throw() T* operator->() const { return ptr; } private: T* ptr; struct ConversionToBool { int dummy; }; public: //use member pointer as implicit conversion to bool (C++ Templates - Vandevoorde/Josuttis; chapter 20) operator int ConversionToBool::* () const { return ptr != NULL ? &ConversionToBool::dummy : NULL; } }; template ComPtr com_dynamic_cast(const ComPtr& other); //throw() //################# Inline Implementation ############################# //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(zen::ComPtr& lhs, zen::ComPtr& rhs) { lhs.swap(rhs); } 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