19#include <QtCore/private/qglobal_p.h>
21#if defined(Q_OS_WIN) || defined(Q_QDOC)
23# include <QtCore/qt_windows.h>
29template <
typename... TInterfaces>
30struct QComObjectTraits
32 static constexpr bool isGuidOf(REFIID riid)
noexcept
34 return ((riid == __uuidof(TInterfaces)) || ...);
65template <
typename TFirstInterface,
typename... TAdditionalInterfaces>
66class QComObject :
public TFirstInterface,
public TAdditionalInterfaces...
69 STDMETHODIMP QueryInterface(REFIID riid,
void **ppvObject) override
74 if (riid == __uuidof(IUnknown)) {
75 *ppvObject =
static_cast<IUnknown *>(
static_cast<TFirstInterface *>(
this));
81 return tryQueryInterface<TFirstInterface, TAdditionalInterfaces...>(riid, ppvObject);
84 STDMETHODIMP_(ULONG) AddRef() override
86 return m_referenceCount.fetch_add(1, std::memory_order_relaxed) + 1;
89 STDMETHODIMP_(ULONG) Release() override
91 const LONG referenceCount = m_referenceCount.fetch_sub(1, std::memory_order_release) - 1;
92 if (referenceCount == 0) {
96 std::atomic_thread_fence(std::memory_order_acquire);
100 return referenceCount;
104 QComObject() =
default;
108 virtual ~QComObject() =
default;
111 std::atomic<LONG> m_referenceCount = 1;
114 template <
typename TInterface,
typename... TRest>
115 HRESULT tryQueryInterface(REFIID riid,
void **ppvObject)
117 if (QtPrivate::QComObjectTraits<TInterface>::isGuidOf(riid)) {
118 *ppvObject =
static_cast<TInterface *>(
this);
124 if constexpr (
sizeof...(TRest) > 0)
125 return tryQueryInterface<TRest...>(riid, ppvObject);
127 *ppvObject =
nullptr;
129 return E_NOINTERFACE;