C++ 可变高阶函数的过载分解
假设我有一个可变的高阶函数C++ 可变高阶函数的过载分解,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,假设我有一个可变的高阶函数 template<typename F, typename ...Args> void execution(F func, Args&&... args) { func(std::forward<Args>(args)...); } 过载解决方案将是 然而,如果只提供其中一个,程序 为什么会发生这种情况?模板参数推断失败的原因 如果我从集合中删除f(),并将其替换为f(arg,arg2)仍然存在一个错误。是否有变通方法
template<typename F, typename ...Args>
void execution(F func, Args&&... args)
{
func(std::forward<Args>(args)...);
}
过载解决方案将是
然而,如果只提供其中一个,程序
f()
,并将其替换为f(arg,arg2)
仍然存在一个错误。是否有变通方法,或者我是否总是必须将函数的属性作为模板参数
execution<void()>(f);
执行(f);
没有可用的特定功能“f”: 简化它:
template<typename F>
void execution(F func)
{}
void f() {}
void f(int arg) {}
int main()
{
execution(f);
return 0;
}
模板
无效执行(F func)
{}
void f(){}
void f(int arg){}
int main()
{
执行(f);
返回0;
}
有两个函数“f”可用于模板参数推断/替换在进行模板类型推断时,编译器不会分析函数中如何使用类型。因此,在推导模板参数时,编译器看不到不同模板参数之间的关系。因此,额外的可变模板参数根本不重要,问题可以简化为
template<typename Func> void execution(Func func);
void f();
void f(int);
execution(f);
模板作废执行(Func Func);
无效f();
无效f(int);
执行(f);
有了这段最小化的代码,模板参数推断失败的原因就显而易见了
您可以通过使第一个参数显式依赖于其余模板参数来解决此问题,例如:
template<typename... Args>
void execution(void (*func)(Args ...), Args ... args)
{
func(std::forward<Args>(args) ...);
}
模板
作废执行(作废(*func)(参数…,参数…)
{
func(std::forward(args)…);
}
您需要一个重载集对象。这是一个表示f
的整个重载函数集的对象:
struct f_overload_set {
template<typename...As>
auto operator()(As&&...as)->
decltype(f(std::declval<As>()...))
{ return f(std::forward<As>(as)...); }
};
struct f_重载集{
模板
自动运算符()(As&&…As)->
decltype(f(std::declval()…)
{返回f(std::forward(as)…);}
};
现在将f_重载{}
传递给模板
函数
<代码>模板<代码>函数值参数必须是值,而在当前C++中没有表示函数的整个重载集的第一类值。符号
f
在每个使用点被消歧为一个重载:但这需要在使用点有一个直接的上下文。上面的问题是在我们有参数的前提下进行消歧。是否存在C++乔恩SKET?这首先是模板参数推导的问题,较少的过载分辨率。C++1y解决方案是编写执行([](auto&&…pp){returnf(std::forward(pp);})代码>。这是一个已知的问题,我猜这个问题有多个重复项。std::function
不需要拒绝无法为模板参数中提供的参数类型调用的函数。这是一个QoI问题。此外,您的解决方案需要在调用站点将f
显式转换为std::function
类型:只有在给定显式目标类型(例如void execution(void(*)(int));
)时,不同函数之间才会发生重载解析。std::function
类型只有构造函数模板,因此不会发生重载解析,并且f
将是不明确的。@dyp:谢谢,我没有注意到std::function
的问题。我已经将代码更改为一个简单的函数指针;虽然灵活性较差,但它应该解决手头的问题。voidfoo(int);模板作废执行(作废(*func)(参数…,参数…);int main(){execution(foo,3.0);}
做什么?Ie,此修复程序不足。@Yakk:它给出了一个错误,因为没有f(double)
。我会考虑预期的行为。你期待什么样的行为?这就解决了问题。我想我已经算出了C++14:#define LIFT(f)[](auto&&…a)->decltype(auto){return f(std::forward(a)…);}
。如果您不想依赖于
,请将std::forward
替换为static\u cast
。
template<typename... Args>
void execution(void (*func)(Args ...), Args ... args)
{
func(std::forward<Args>(args) ...);
}
struct f_overload_set {
template<typename...As>
auto operator()(As&&...as)->
decltype(f(std::declval<As>()...))
{ return f(std::forward<As>(as)...); }
};