Effective use and design of COM smart Pointers-cla18: Heavy-duty operators should not distort their Semantics

Source: Internet
Author: User
Clause 18: overload operators should not distort their semantics more terms go to source: http://blog.csdn.net/liuchang5

_ Com_ptr_t calls the _ compareunknown function on various comparison operators. Let's see what he has done:

template<typename _InterfaceType> bool operator<(_InterfaceType* p) {    return _CompareUnknown(p) < 0;}
template<typename _InterfaceType> bool operator==(_InterfaceType* p) {    return _CompareUnknown(p) == 0;}
template<typename _InterfacePtr> int _CompareUnknown(_InterfacePtr p) {    IUnknown* pu1, *pu2;    if (m_pInterface != NULL) {        HRESULT hr =m_pInterface->QueryInterface(            __uuidof(IUnknown), reinterpret_cast<void**>(&pu1)        );        if (FAILED(hr)) {            _com_issue_error(hr);            pu1 = NULL;        }        else {            pu1->Release();        }    }    else {         pu1 = NULL;    }    if (p != NULL) {        HRESULT hr = p->QueryInterface(            __uuidof(IUnknown), reinterpret_cast<void**>(&pu2)        );        if (FAILED(hr)) {            _com_issue_error(hr);            pu2 = NULL;        }        else {            pu2->Release();        }    }    else {        pu2 = NULL;    }return pu1 - pu2;}

It seems that his approach is a bit complicated, but with a slight explanation, you will understand: _ compareunknown queries the iunknonw interfaces for the two interfaces respectively, and then determines whether the queried interfaces are the same. You may be surprised! The comparison operator of a smart pointer is not a comparison pointer, but a comparison of whether two pointers point to the same component!

This practice is indeed unpredictable, but you may understand the reasons behind his history. In VB, a common com variable is mapped to VC and a smart pointer pointing to com is created. In VB, the com variable should be determined to determine whether it points to the same component. Therefore, _ com_ptr_t does this, but the semantics is indeed quite different from that of common pointers. So sometimes it is confusing to compare it with the same interface pointer. As follows:

Extends spcalculator (clsid_calculator); extends = spcalculator; iunknown * piunknown = spcalculator; icalculator * pcalculator = spcalculator; extends * operator = spcomdebugger; If (condition = piunknown) {dosomething (); // The statement is not executed because the two pointer addresses are different. } If (pcomdebugger = spcalculator) {dosomething (); // This statement is executed because the two interface pointers refer to the same object. }

Let's look at the comparison function of ccomptr. It may look like you want.

bool operator!=(_In_opt_ T* pT) const{    return !operator==(pT);}bool operator==(_In_opt_ T* pT) const throw(){    return p == pT;}bool operator<(_In_opt_ T* pT) const throw(){    return p < pT;}

Hmm ~ However, you cannot find functions such as> =,>, and <=. Where did they go? Looking back at the history of ATL, you seem to realize that this is really simple. It's simple. It's just fine. For the relationships between greater than or equal to and less than or equal to, you can use <and = to combine them. Providing only one <means that ccomptr follows the strict weak order convention. This allows your smart pointers to be removed from associated containers such as set and map (these associated containers are compared using the equivalent concept based on strict weak order, rather than equivalent ).

And _ com_ptr_t is not so lucky. To be compatible with the features of VB and other explanatory languages. The code has to be appended with the single-camera version of each type of comparison function, but this is not enough. In many cases, a binary version is required for comparison between smart pointers and non-smart pointers:

template<typename _Interface> bool operator<=(int null, _com_ptr_t<_Interface>& p) {    if (null != 0) {        _com_issue_error(E_POINTER);    }    return p >= NULL;}template<typename _Interface, typename _InterfacePtr>bool operator<=(_Interface* i, _com_ptr_t<_InterfacePtr>& p) {    return p >= i;}

Now you know. For special reasons, do not use a comparison operator to determine whether a smart pointer points to a unified component. This distorted operator semantics will make your code hard to understand. When you need this function, you should provide a function for the corresponding function. This will make your code clearer and easier to understand. Smart pointers will also become concise:

// Compare two objects for equivalencebool IsEqualObject(_In_opt_ IUnknown* pOther) throw(){    if (p == NULL && pOther == NULL)        return true;// They are both NULL objects    if (p == NULL || pOther == NULL)        return false;// One is NULL the other is not    CComPtr<IUnknown> punk1;    CComPtr<IUnknown> punk2;    p->QueryInterface(__uuidof(IUnknown), (void**)&punk1);    pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2);    return punk1 == punk2;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.