Calvin Hu
Calvin Hu

Reputation: 4005

test if CComPtr is null in COM

I have a question regarding the usage of COM smart pointer class CComPtr. I was following an example from the documentation and it seems the code does not call CoCreateInstance() on the CComPtr (it merely declares it before assigning it value).

So I wrote a test program like this:

#include "stdafx.h"
#include "atlbase.h"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
    CComPtr<int> myint = nullptr;
    if (myint == nullptr) {
        std::cout << "yes" << std::endl;
    }
    return 0;
}

And it gives the following error in visual-studio 2013:

------ Build started: Project: ConsoleApplication2, Configuration: Debug Win32 ------

  ConsoleApplication2.cpp

c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcomcli.h(177): error C2227: left of '->Release' must point to class/struct/union/generic type

          type is 'int *'

          c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcomcli.h(175) : while compiling class template member function 'ATL::CComPtrBase::~CComPtrBase(void) throw()'

          with

          [

              T=int

          ]

          c:\users\calvi_000\documents\visual studio 2013\projects\consoleapplication2\consoleapplication2\consoleapplication2.cpp(18) : see reference to function template instantiation 'ATL::CComPtrBase::~CComPtrBase(void) throw()' being compiled

          with

          [

              T=int

          ]

          c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcomcli.h(317) : see reference to class template instantiation 'ATL::CComPtrBase' being compiled

          with

          [

              T=int

          ]

          c:\users\calvi_000\documents\visual studio 2013\projects\consoleapplication2\consoleapplication2\consoleapplication2.cpp(10) : see reference to class template instantiation 'ATL::CComPtr' being compiled

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Why is it illegal to assign a nullptr to a CComPtr object ? Is there any method that we can use to check whether or not a CComPtr owns any objects ? Will a call like if (myint == nullptr) enough to check if this smart pointer does not own any object ?

Upvotes: 2

Views: 4539

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596713

Why is it illegal to assign a nullptr to a CComPtr object ?

It is not. As Hans pointed out, CComPtr can only be used with COM interfaces, int is not a compatible type. That is what the compiler error is telling you:

error C2227: left of '->Release' must point to class/struct/union/generic type

          type is 'int *'

So the problem is not that you are assigning nullptr, but that int does not have a Release() method, which CComPtr requires. An IUnknown (or derived) interface does have a Release() method.

Is there any method that we can use to check whether or not a CComPtr owns any objects ? Will a call like if (myint == nullptr) enough to check if this smart pointer does not own any object ?

If you read the CComPtr documentation more carefully, you would see that CComPtr derives from CComPtrBase, which implements operator!(), operator T*() and operator==() operators (so CComPtr will act like a raw pointer), as well as an IsEqualObject() method:

int _tmain(int argc, _TCHAR* argv[])
{
    CComPtr<IUnknown> myUnk = nullptr;
    if (!myUnk) { // calls myUnk.operator!() ...
        std::cout << "null" << std::endl;
    else
        std::cout << "not null" << std::endl;
    }
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    CComPtr<IUnknown> myUnk = nullptr;
    if (myUnk) { // calls myUnk.operator IUnknown*() ...
        std::cout << "not null" << std::endl;
    else
        std::cout << "null" << std::endl;
    }
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    CComPtr<IUnknown> myUnk = nullptr;
    if (myUnk == nullptr) { // calls myUnk.operator==(IUnknown*) ...
        std::cout << "null" << std::endl;
    else
        std::cout << "not null" << std::endl;
    }
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    CComPtr<IUnknown> myUnk = nullptr;
    if (myUnk.IsEqualObject(nullptr)) {
        std::cout << "null" << std::endl;
    else
        std::cout << "not null" << std::endl;
    }
    return 0;
}

Upvotes: 10

Related Questions