Advertisement
Guest User

WTL's ComPtr

a guest
Sep 18th, 2011
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.21 KB | None | 0 0
  1. template <typename T>
  2. class ComPtr
  3. {
  4. public:
  5.     typedef T InterfaceType;
  6.  
  7. protected:
  8.     InterfaceType *ptr_;
  9.     template<class U> friend class ComPtr;
  10.  
  11.     void InternalAddRef() const throw()
  12.     {
  13.         if (ptr_ != nullptr)
  14.         {
  15.             ptr_->AddRef();
  16.         }
  17.     }
  18.  
  19.     unsigned long InternalRelease() throw()
  20.     {
  21.         unsigned long ref = 0;
  22.         T* temp = ptr_;
  23.  
  24.         if (temp != nullptr)
  25.         {
  26.             ptr_ = nullptr;
  27.             ref = temp->Release();
  28.         }
  29.        
  30.         return ref;
  31.     }
  32.  
  33. public:
  34. #pragma region constructors
  35.     ComPtr() throw() : ptr_(nullptr)
  36.     {
  37.     }
  38.  
  39.     ComPtr(decltype(__nullptr)) throw() : ptr_(nullptr)
  40.     {
  41.     }
  42.  
  43.     template<class U>
  44.     ComPtr(_In_opt_ U *other) throw() : ptr_(other)
  45.     {
  46.         InternalAddRef();
  47.     }
  48.  
  49.     ComPtr(const ComPtr& other) throw() : ptr_(other.ptr_)
  50.     {
  51.         InternalAddRef();
  52.     }
  53.  
  54.     // copy ctor that allows to instanatiate class when U* is convertible to T*
  55.     template<class U>
  56.     ComPtr(const ComPtr<U> &other, typename Details::EnableIf<__is_convertible_to(U*, T*), void *>::type * = 0) throw() :
  57.         ptr_(other.ptr_)
  58.     {
  59.         InternalAddRef();
  60.     }
  61.  
  62.     ComPtr(_Inout_ ComPtr &&other) throw() : ptr_(nullptr)
  63.     {
  64.         if (this != reinterpret_cast<ComPtr*>(&reinterpret_cast<byte&>(other)))
  65.         {
  66.             Swap(other);
  67.         }
  68.     }
  69.  
  70.     // Move ctor that allows instantiation of a class when U* is convertible to T*
  71.     template<class U>
  72.     ComPtr(_Inout_ ComPtr<U>&& other, typename Details::EnableIf<__is_convertible_to(U*, T*), void *>::type * = 0) throw() :
  73.         ptr_(other.ptr_)
  74.     {
  75.         other.ptr_ = nullptr;
  76.     }
  77. #pragma endregion
  78.  
  79. #pragma region destructor
  80.     ~ComPtr() throw()
  81.     {
  82.         InternalRelease();
  83.     }
  84. #pragma endregion
  85.  
  86. #pragma region assignment
  87.     ComPtr& operator=(decltype(__nullptr)) throw()
  88.     {
  89.         InternalRelease();
  90.         return *this;
  91.     }
  92.  
  93.     ComPtr& operator=(_In_opt_ T *other) throw()
  94.     {
  95.         if (ptr_ != other)
  96.         {
  97.             ComPtr(other).Swap(*this);
  98.         }
  99.         return *this;
  100.     }
  101.  
  102.     template <typename U>
  103.     ComPtr& operator=(_In_opt_ U *other) throw()
  104.     {
  105.         ComPtr(other).Swap(*this);
  106.         return *this;
  107.     }
  108.  
  109.     ComPtr& operator=(const ComPtr &other) throw()
  110.     {
  111.         if (ptr_ != other.ptr_)
  112.         {
  113.             ComPtr(other).Swap(*this);
  114.         }
  115.         return *this;
  116.     }
  117.  
  118.     template<class U>
  119.     ComPtr& operator=(const ComPtr<U>& other) throw()
  120.     {
  121.         ComPtr(other).Swap(*this);
  122.         return *this;
  123.     }
  124.  
  125.     ComPtr& operator=(_Inout_ ComPtr &&other) throw()
  126.     {
  127.         ComPtr(static_cast<ComPtr&&>(other)).Swap(*this);
  128.         return *this;
  129.     }
  130.  
  131.     template<class U>
  132.     ComPtr& operator=(_Inout_ ComPtr<U>&& other) throw()
  133.     {
  134.         ComPtr(static_cast<ComPtr<U>&&>(other)).Swap(*this);
  135.         return *this;
  136.     }
  137. #pragma endregion
  138.  
  139. #pragma region modifiers
  140.     void Swap(_Inout_ ComPtr&& r) throw()
  141.     {
  142.         T* tmp = ptr_;
  143.         ptr_ = r.ptr_;
  144.         r.ptr_ = tmp;
  145.     }
  146.  
  147.     void Swap(_Inout_ ComPtr& r) throw()
  148.     {
  149.         T* tmp = ptr_;
  150.         ptr_ = r.ptr_;
  151.         r.ptr_ = tmp;
  152.     }
  153. #pragma endregion
  154.  
  155.     operator Details::BoolType() const throw()
  156.     {
  157.         return Get() != nullptr ? &Details::BoolStruct::Member : nullptr;
  158.     }
  159.  
  160.     T* Get() const throw()
  161.     {
  162.         return ptr_;
  163.     }
  164.  
  165.     typename Details::RemoveIUnknown<InterfaceType>::ReturnType* operator->() const throw()
  166.     {
  167.         return static_cast<typename Details::RemoveIUnknown<InterfaceType>::ReturnType*>(ptr_);
  168.     }    
  169.  
  170.     Details::ComPtrRef<ComPtr<T>> operator&() throw()
  171.     {
  172.         return Details::ComPtrRef<ComPtr<T>>(this);
  173.     }
  174.  
  175.     const Details::ComPtrRef<const ComPtr<T>> operator&() const throw()
  176.     {
  177.         return Details::ComPtrRef<const ComPtr<T>>(this);
  178.     }
  179.  
  180.     T* const* GetAddressOf() const throw()
  181.     {
  182.         return &ptr_;
  183.     }
  184.  
  185.     T** GetAddressOf() throw()
  186.     {
  187.         return &ptr_;
  188.     }
  189.  
  190.     T** ReleaseAndGetAddressOf() throw()
  191.     {
  192.         InternalRelease();
  193.         return &ptr_;
  194.     }
  195.  
  196.     T* Detach() throw()
  197.     {
  198.         T* ptr = ptr_;
  199.         ptr_ = nullptr;
  200.         return ptr;
  201.     }
  202.  
  203.     void Attach(_In_opt_ InterfaceType* other) throw()
  204.     {
  205.         if (ptr_ != nullptr)
  206.         {
  207.             auto ref = ptr_->Release();
  208.             (ref);
  209.             // Attaching to the same object only works if duplicate references are being coalesced. Otherwise
  210.             // re-attaching will cause the pointer to be released and may cause a crash on a subsequent dereference.
  211.             __WRL_ASSERT__(ref != 0 || ptr_ != other);
  212.         }
  213.  
  214.         ptr_ = other;
  215.     }
  216.  
  217.     unsigned long Reset()
  218.     {
  219.         return InternalRelease();
  220.     }
  221.  
  222.     HRESULT CopyTo(_Outptr_result_maybenull_ InterfaceType** ptr) const throw()
  223.     {
  224.         InternalAddRef();
  225.         *ptr = ptr_;
  226.         return S_OK;
  227.     }
  228.  
  229.     HRESULT CopyTo(REFIID riid, _Outptr_result_nullonfailure_ void** ptr) const throw()
  230.     {        
  231.         return ptr_->QueryInterface(riid, ptr);
  232.     }
  233.  
  234.     template<typename U>
  235.     HRESULT CopyTo(_Outptr_result_nullonfailure_ U** ptr) const throw()
  236.     {        
  237.         return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(ptr));
  238.     }
  239.  
  240.     // query for U interface
  241.     template<typename U>
  242.     HRESULT As(_Out_ Details::ComPtrRef<ComPtr<U>> p) const throw()
  243.     {
  244.         return ptr_->QueryInterface(__uuidof(U), p);
  245.     }
  246.  
  247.     // query for U interface
  248.     template<typename U>
  249.     HRESULT As(_Out_ ComPtr<U>* p) const throw()
  250.     {
  251.         return ptr_->QueryInterface(__uuidof(U), reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
  252.     }
  253.  
  254.     // query for riid interface and return as IUnknown
  255.     HRESULT AsIID(REFIID riid, _Out_ ComPtr<IUnknown>* p) const throw()
  256.     {
  257.         return ptr_->QueryInterface(riid, reinterpret_cast<void**>(p->ReleaseAndGetAddressOf()));
  258.     }
  259.  
  260.     HRESULT AsWeak(_Out_ WeakRef* pWeakRef) const throw()
  261.     {
  262.         return Microsoft::WRL::AsWeak(ptr_, pWeakRef);
  263.     }
  264. };    // ComPtr
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement