给出以下代码:
template <typename T>
bool TryQueryInterface(
IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
if (InterfaceProperties<T>::GetIID() == riid)
{
void *underlying;
HRESULT result = in_toQuery->QueryInterface(riid, &underlying);
if (SUCCEEDED(result))
{
*ppvObject = new typename InterfaceProperties<T>::WrapperClass(
*this,
(T*)underlying,
in_parent);
}
return true;
}
return false;
}
template <typename T, typename... Interfaces>
bool TryQueryInterfaces(
IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterface<T>(in_toQuery, riid, ppvObject, in_parent, out_result) ||
TryQueryInterfaces<Interfaces...>(in_toQuery, riid, ppvObject, in_parent, out_result);
}
template <typename T>
bool TryQueryInterfaces(
IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterface<T>(in_toQuery, riid, ppvObject, in_parent, out_result);
}
我收到以下错误:
error C2668: 'TryQueryInterfaces' : ambiguous call to overloaded function
TryQueryInterfaces<ITrusteeGroupAdmin>(IUnknown *,const IID &,void **,ComObject *,HRESULT)'
or TryQueryInterfaces<ITrusteeGroupAdmin,>(IUnknown *,const IID &,void **,ComObject *,HRESULT)'
while trying to match the argument list '(IUnknown *, const IID, void **, ComObject *, HRESULT)'
see reference to function template instantiation 'bool TryQueryInterfaces<ITrusteeAdmin,ITrusteeGroupAdmin>(IUnknown *,const IID &,void **,ComObject *,HRESULT)' being compiled
我在这里缺少什么?如何为递归构造一个明确的基本案例?
答案 0 :(得分:3)
这是不明确的,因为参数包Interfaces...
可能为空。确保至少采用一个参数加上一些额外的(可能为零)参数。将第二种方法更改为:
template <typename T, typename Interface, typename... Interfaces>
bool TryQueryInterfaces(
IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterface<T>(in_toQuery, riid, ppvObject, in_parent, out_result) ||
TryQueryInterfaces<Interface, Interfaces...>(in_toQuery, riid, ppvObject, in_parent, out_result);
}
答案 1 :(得分:3)
使用可变参数模板重载函数与使用常规模板稍有不同。
你可以超载:
void foo()
{
}
和
template <typename Arg1, typename ...Args>
void foo()
{
}
但不是
template <typename Arg1>
void foo()
{
}
和
template <typename Arg1, typename ...Args>
void foo()
{
}
因为当有一个参数时,无法消除要调用的函数的歧义。
在您的情况下,您可以使用帮助程序类来处理调用。
// Forward declaration of the helper class and its template arguments.
template <typename ...Types> struct TryQueryInterfacesHelper;
// helper class with just one argument.
template <typename T>
struct TryQueryInterfacesHelper<T>
{
bool operator()(IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterface<T>(in_toQuery, riid, ppvObject, in_parent, out_result);
}
};
// helper class with more than one argument.
template <typename T, typename ...Interfaces>
struct TryQueryInterfacesHelper<T, Interfaces...>
{
bool operator()(IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterface<T>(in_toQuery, riid, ppvObject, in_parent, out_result) ||
TryQueryInterfacesHelper<Interfaces...>()(in_toQuery, riid, ppvObject, in_parent, out_result);
}
};
template <typename... Interfaces>
bool TryQueryInterfaces(
IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
// Implement the function using the helper class.
return TryQueryInterfacesHelper<Interfaces...>()(in_toQuery, riid, ppvObject, in_parent, out_result);
}
这是一个用更简单的类和函数测试想法的示例程序。
#include <iostream>
template <class ...Types> struct X;
template <class T>
struct X<T>
{
void operator()(){std::cout << "Came to X<T>\n";}
};
template <class T, class ...Types>
struct X<T, Types...>
{
void operator()(){std::cout << "Came to X<T, Types...>\n"; X<Types...>()();}
};
template <class ...Types>
void foo()
{
X<Types...>()();
}
int main()
{
foo<int>();
foo<int, double>();
foo<int, double, char>();
}
输出:
Came to X<T>
Came to X<T, Types...>
Came to X<T>
Came to X<T, Types...>
Came to X<T, Types...>
Came to X<T>
答案 2 :(得分:2)
另一个解决方案是使用enable_if
仅在包非空时使用参数包启用TryQueryInterfaces
实现。您还应该重新排列两个TryQueryInterfaces
实现,以便处理单个模板参数的终端案例高于另一个。这允许参数包版本中的名称查找成功。
这也允许你摆脱TryQueryInterface
实现。
template<typename T>
bool TryQueryInterfaces(IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
// query single interface here
}
template<typename T, typename... Interfaces>
typename std::enable_if<sizeof...(Interfaces) != 0, bool>::type
TryQueryInterfaces(IUnknown* in_toQuery,
REFIID riid,
void **ppvObject,
ComObject* in_parent,
HRESULT out_result)
{
return TryQueryInterfaces<T>(in_toQuery, riid, ppvObject, in_parent, out_result) ||
TryQueryInterfaces<Interfaces...>(in_toQuery, riid, ppvObject, in_parent, out_result);
}
答案 3 :(得分:0)
template <typename T>
void foo();
和
template <typename T, template ...R>
void foo();
两者都匹配foo<X>();
为了发挥一些作用,请使用两种类型:
template <typename T1, typename T2, template ...R>
void foo();