Skip to content

Instantly share code, notes, and snippets.

@jugemjugem
Last active January 21, 2017 16:49
Show Gist options
  • Save jugemjugem/190886f4fe152f2fd6cd to your computer and use it in GitHub Desktop.
Save jugemjugem/190886f4fe152f2fd6cd to your computer and use it in GitHub Desktop.
variadic template と queryinterface
// msvc2013 sp3 でコンパイルは通るけど、正しく動作するかは不明なコード片です。
//
// Some IDL Generated interfaces's header
// こんな idl 生成のインターフェイスがあるとき
//
MIDL_INTERFACE("GUID IA")
IA : public IUnknown
{};
MIDL_INTERFACE("GUID IB")
IB : public IA
{};
// MyComObject.cpp
// My Implimentation
// 実装クラス
// 説明の都合、QIのみ
class MyComObject : public IB
{
private:
// 対象のインターフェイスのIIDを順番にチェックするためのヘルプクラス。
// この型ではArg1 (先頭の型)についてのみ IID のチェックを行う。
template<class Arg1=void, class ...Args>
struct TClass
{
// QI 問い合わせの実行。
static HRESULT QI_Util(MyComObject* pThis, REFIID iid, void** ppv)
{
using arg_t = typename type;
if( iid == __uuidof( Arg1 ) )
{
// 普通にキャスト
*ppv = static_cast<Arg1*>( pThis );
// 見つかったので、S_OK & 終了。
return S_OK;
}
// 今の型は対象ではなかったので、残りの型でチェックを繰り返す。
return TClass<Args...>::QI_Util(pThis, iid, ppv);
}
};
// 全部の型でチェックが済んだときのエラー返却用。
template<>
struct TClass<void>
{
static HRESULT QI_Util(MyComObject* pThis, REFIID iid, void** ppv)
{
// 無かったのでエラー(E_NOINTERFACE)を返す。
return E_NOINTERFACE;
}
};
public:
// QI の実装
STDMETHOD(QueryInterface)( REFIID iid, void** ppv )override
{
// QIできる型を並べて置く。
return TClass<IUnknown, IA, IB>::QI_Util(this,iid, ppv);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment