假设我有一个可变高阶函数
template<typename F, typename ...Args>
void execution(F func, Args&&... args)
{
func(std::forward<Args>(args)...);
}
然后为此过载集
void f() {}
void f(int arg) {}
重载分辨率为impossible
int main()
{
execution(f, 1);
execution(f);
return 0;
}
然而,如果只提供两者中的任何一个,程序compiles
如果我从集合中移除f()
并将其替换为f(arg, arg2)
,那么仍然是problem。是否有解决方法,或者我是否总是将[{3}}函数作为模板参数?
execution<void()>(f);
答案 0 :(得分:8)
在进行模板类型推导时,编译器不会分析函数内部如何使用类型。因此,在推导模板参数时,编译器看不到不同模板参数之间的关系。因此,额外的可变参数模板参数根本不重要,问题可以简化为
template<typename Func> void execution(Func func);
void f();
void f(int);
execution(f);
使用此最小化代码,显然为什么模板参数推断失败。
您可以通过使第一个参数明确依赖于剩余的模板参数来解决此问题,例如:
template<typename... Args>
void execution(void (*func)(Args ...), Args ... args)
{
func(std::forward<Args>(args) ...);
}
答案 1 :(得分:3)
您需要一个重载集对象。这是一个对象,表示f
:
struct f_overload_set {
template<typename...As>
auto operator()(As&&...as)->
decltype(f(std::declval<As>()...))
{ return f(std::forward<As>(as)...); }
};
现在将f_overload_set{}
传递给您的template
函数。
template
的函数值参数必须是值,并且在当前的C ++中,没有表示函数的整个重载集的第一类值。符号f
在每个使用点被消除歧义为一个重载:但这需要在使用点立即上下文。上述内容推迟了歧义消除,直到我们有了适当的论据。
答案 2 :(得分:1)
没有特定的功能'f'可用:
简化它:
template<typename F>
void execution(F func)
{}
void f() {}
void f(int arg) {}
int main()
{
execution(f);
return 0;
}
您有两个函数'f'可用于模板参数扣除/替换