Шаблоны CComPtr и CComQIPtr предлагает нам ATL. Так что ести вы не используете ATL у себя в проекте, то ваш выбор однозначен - _com_ptr_t. Тут даже думать не надо - особого смысла пораждать зависимость от ATL ради CComPtr/CComQIPtr нет.
У _com_ptr_t есть полезный макрос для создания конкретных типов (через typedef): _COM_SMARTPTR_TYPEDEF. Выглядит это так:
// = typedef _com_ptr_t<...> IFooBarPtr;Еще бОльшая прелесть состоит в том, что для большинства интерфейсов уже заданы такие typedef-ы, то есть можно смело писать
_COM_SMARTPTR_TYPEDEF(IFooBar, __uuidof(IFooBar));
...
IFooBarPtr FooBar;
IHTMLDocument2Ptr Document;
без соответствующего тайпдефа. Однако засада в том, что сделаны не все тайпдефы и для некоторых интерфейсов придется либо самим объявлять тип через _COM_SMARTPTR_TYPEDEF или использовать _com_ptr_t напрямую._com_ptr_t, как и CComQIPtr умеют вызывать QueryInterface "на ходу", что довольно удобно:
IDispatchPtr RawDocument = GetDocument();Небольшим плюсом CComQIPtr может служить его бОльшая лаконичность по сравнению с _com_ptr_t:
IHTMLDocument2Ptr Document(RawDocument); // здесь автоматически вызывается QueryInterface
CComQIPtr<IHTMLDocument4> Document;
vs
_com_ptr_t<IHTMLDocument4, &__uuidof(IHTMLDocument4)> Document;
Вывод из этого я делаю такой: если используете ATL — берите CComQIPtr, если нет — _com_ptr_t. Если вдруг придется "слезть" с ATL, то будет довольно просто перевести код с CComQIPtr на _com_ptr_t.
Post scriptum
Все перечисленные выше умные указатели переопределяют operator& так, что он возвращает адрес обычного указателя, вместо адреса умного указателя. Это очень удобно для таких вот вызовов, которых в COM предостаточно:
IWebBrowserPtr Browser = GetBrowser();Соответственно, если будет желание положить элемент в контейнер, то оператору & очень желательно вернуть прежнюю логику. Например, обернув умный указатель в CAdapt из ATL:
IDispatchPtr Document;
// calling HRESULT STDMETHODCALLTYPE get_Document(IDispatch **ppDisp);
Browser->get_Document(&Document);
std::vector< CAdapt< CComQIPtr<IDispatch> > > ObjectsА если понадобится, то можно в любой момент сделать "срезку" до CComQIPtr/_com_ptr_t с его переопределенным оператором &:
BOOST_FOREACH(CComQIPtr<IDispatch> &Object, Objects)
Browser->get_Document(&Object);
PPS. Дискуссии по теме: здесь и здесь.