#pragma once namespace win { template class ComPtr; template class ComPtrRef { private: ComPtr& m_ComPtr; ComPtrRef(ComPtr& comPtr) : m_ComPtr(comPtr) { } friend class ComPtr; public: inline operator T**() { return m_ComPtr.ReleaseAndGetAddressOf(); } inline operator void**() { return reinterpret_cast(m_ComPtr.ReleaseAndGetAddressOf()); } inline T* operator*() throw () { return m_ComPtr; } }; template class ComPtr { private: T *ptr; public: inline ComPtr(void) : ptr(NULL) {} inline ~ComPtr(void) { this->Free(); } ComPtr(T *ptr) { if (NULL != (this->ptr = ptr)) { this->ptr->AddRef(); } } ComPtr(const ComPtr &ptr) { if (NULL != (this->ptr = ptr.ptr)) { this->ptr->AddRef(); } } inline bool operator!() const { return (NULL == this->ptr); } inline operator T*() const { return this->ptr; } inline T *operator->() const { //_assert(NULL != this->ptr); return this->ptr; } inline T &operator*() { //_assert(NULL != this->ptr); return *this->ptr; } inline ComPtrRef operator&() { return ComPtrRef(*this); } const ComPtr &operator=(T *ptr) { if (this->ptr != ptr) { this->Free(); if (NULL != (this->ptr = ptr)) { this->ptr->AddRef(); } } return *this; } const ComPtr &operator=(const ComPtr &ptr) { if (this->ptr != ptr.ptr) { this->Free(); if (NULL != (this->ptr = ptr.ptr)) { this->ptr->AddRef(); } } return *this; } void Free(void) { if (NULL != this->ptr) { this->ptr->Release(); this->ptr = NULL; } } inline T** ReleaseAndGetAddressOf() { Free(); return &ptr; } template inline HRESULT As(ComPtrRef p) const throw () { return ptr->QueryInterface(__uuidof(U), p); } inline bool operator==(std::nullptr_t) const { return this->ptr == nullptr; } template inline bool operator==(U* other) { if (ptr == nullptr || other == nullptr) return ptr == other; ComPtr meUnknown; ComPtr otherUnknown; if (FAILED(this->ptr->QueryInterface(__uuidof(IUnknown), &meUnknown))) return false; if (FAILED(other->QueryInterface(__uuidof(IUnknown), &otherUnknown))) return false; return static_cast(meUnknown) == static_cast(otherUnknown); } template inline bool operator==(ComPtr& other) { return *this == static_cast(other); } inline bool operator!=(std::nullptr_t) const { return this->ptr != nullptr; } template inline bool operator!=(U* other) { return !(*this == other); } template inline bool operator!=(ComPtr& other) { return *this != static_cast(other); } }; }