18#include <QtCore/private/qglobal_p.h>
20#if defined(Q_OS_WIN) || defined(Q_QDOC)
22# include <QtCore/qt_windows.h>
28template <
typename... TInterfaces>
29struct QComObjectTraits
31 static constexpr bool isGuidOf(REFIID riid)
noexcept
33 return ((riid == __uuidof(TInterfaces)) || ...);
64template <
typename TFirstInterface,
typename... TAdditionalInterfaces>
65class QComObject :
public TFirstInterface,
public TAdditionalInterfaces...
68 STDMETHODIMP QueryInterface(REFIID riid,
void **ppvObject) override
73 if (riid == __uuidof(IUnknown)) {
74 *ppvObject =
static_cast<IUnknown *>(
static_cast<TFirstInterface *>(
this));
80 return tryQueryInterface<TFirstInterface, TAdditionalInterfaces...>(riid, ppvObject);
83 STDMETHODIMP_(ULONG) AddRef() override
85 return m_referenceCount.fetch_add(1, std::memory_order_relaxed) + 1;
88 STDMETHODIMP_(ULONG) Release() override
90 const LONG referenceCount = m_referenceCount.fetch_sub(1, std::memory_order_release) - 1;
91 if (referenceCount == 0) {
95 std::atomic_thread_fence(std::memory_order_acquire);
99 return referenceCount;
103 QComObject() =
default;
107 virtual ~QComObject() =
default;
110 std::atomic<LONG> m_referenceCount = 1;
113 template <
typename TInterface,
typename... TRest>
114 HRESULT tryQueryInterface(REFIID riid,
void **ppvObject)
116 if (QtPrivate::QComObjectTraits<TInterface>::isGuidOf(riid)) {
117 *ppvObject =
static_cast<TInterface *>(
this);
123 if constexpr (
sizeof...(TRest) > 0)
124 return tryQueryInterface<TRest...>(riid, ppvObject);
126 *ppvObject =
nullptr;
128 return E_NOINTERFACE;