# pragma once template class com_ptr { //private: // typedef void (com_ptr::*bool_type)() const; // void safe_bool() const {} // // public: com_ptr(): _ptr(nullptr) { } com_ptr(T* ptr, bool add_ref = false): _ptr(ptr) { if (_ptr && add_ref) _ptr->AddRef(); } com_ptr(const com_ptr& rhs): _ptr(rhs._ptr) { if (_ptr) _ptr->AddRef(); } com_ptr(com_ptr&& rhs): _ptr(rhs._ptr) { rhs._ptr = nullptr; } template com_ptr(const com_ptr& rhs): _ptr(rhs._ptr) { if (_ptr) _ptr->AddRef(); } ~com_ptr() { if (_ptr) _ptr->Release(); } com_ptr& operator = (const com_ptr& rhs) { com_ptr(rhs).swap(*this); return *this; } com_ptr& operator = (com_ptr&& rhs) { com_ptr(static_cast(rhs)).swap(*this); return *this; } template com_ptr& operator = (const com_ptr& rhs) { com_ptr(rhs).swap(*this): return *this; } com_ptr& operator = (T* rhs) { com_ptr(rhs).swap(*this); return *this; } //operator bool_type() const //{ // return _ptr ? &com_ptr::safe_bool : nullptr; //} //bool_type operator !() const //{ // return !((bool_type)*this); //} void reset() { com_ptr().swap(*this); } void reset(T* rhs) { com_ptr(rhs).swap(*this); } void reset(T* rhs, bool add_ref) { com_ptr(rhs, add_ref).swap(*this); } T* get() const { return _ptr; } T* detach() { auto result = _ptr; _ptr = nullptr; return result; } void swap(com_ptr& rhs) { T* temp = rhs._ptr; rhs._ptr = _ptr; _ptr = temp; } T& operator * () const { return *_ptr; } T* operator -> () const { return _ptr; } operator T* () const { return _ptr; } T** operator & () { return &_ptr; } private: T* _ptr; }; template inline bool operator==(const com_ptr& a, const com_ptr& b) { return a.get() == b.get(); } template inline bool operator!=(const com_ptr& a, const com_ptr& b) { return a.get() != b.get(); } template inline bool operator==(const com_ptr& a, U* b) { return a.get() == b; } template inline bool operator!=(const com_ptr& a, U* b) { return a.get() != b; } template inline bool operator==(T* a, const com_ptr& b) { return a == b.get(); } template inline bool operator!=(T* a, const com_ptr& b) { return a != b.get(); } template inline bool operator==(const com_ptr& p, std::nullptr_t) { return p.get() == nullptr; } template inline bool operator==(std::nullptr_t, const com_ptr& p) { return p.get() == nullptr; } template inline bool operator!=(const com_ptr& p, std::nullptr_t) { return p.get() != nullptr; } template inline bool operator!=(std::nullptr_t, const com_ptr& p) { return p.get() != nullptr; } template inline bool operator<(const com_ptr& a, const com_ptr& b) { return std::less()(a.get(), b.get()); } template inline bool operator<=(const com_ptr& a, const com_ptr& b) { return std::less_equal()(a.get(), b.get()); } template inline bool operator>(const com_ptr& a, const com_ptr& b) { return std::greater()(a.get(), b.get()); } template inline bool operator>=(const com_ptr& a, const com_ptr& b) { return std::greater_equal()(a.get(), b.get()); } template void swap(com_ptr & lhs, com_ptr & rhs) { lhs.swap(rhs); }