我有这样的功能:
void loadData(std::function<void (std::string, std::string, std::string)> callback)
{
// data loading stuff
callback(body, subject, header);
}
问题是我不一定需要在回调函数中使用subject
和header
。现在我正以这种方式处理它:
loadData([](std::string body, std::string, std::string){
std::cout << body;
})
我想用
替换它loadData([](std::string body){
std::cout << body;
})
并自动传递给回调函数尽可能多的参数。
我不想为所有3个可能的参数计数手动重载loadData
函数。我也不想在调用站点上使用任何更复杂的lambda语法,因为我的库应该清楚,供其他人使用。
这可能是使用C ++ STL和Boost吗?
答案 0 :(得分:6)
如何使用...
忽略以下参数?
loadData([](std::string body, ...){
std::cout << body;
})
<小时/> 正如StoryTeller指出的那样(感谢!),对于非平凡类型,可能不支持使用省略号(有关详细信息,请参阅[expr.call]p9)。
要避免此问题,如果您可以使用C ++ 14,则可以使用auto ...
(更好auto && ...
以避免不必要的副本;感谢Yakk)。
loadData([](std::string body, auto && ...){
std::cout << body;
})
答案 1 :(得分:1)
你可以围绕lambda创建一个包装器。
template<typename L>
struct OptionalWrapper {
OptionalWrapper(L l) : lambda{std::move(l)} {}
void operator()(std::string body, std::string subject, std::string header) const {
call(lambda, body, subject, header);
}
private:
template<typename T>
auto call(T& l, std::string body, std::string subject, std::string header) const
-> decltype(l(body, subject, header))
{
return l(body, subject, header);
}
template<typename T>
auto call(T& l, std::string body, std::string subject, std::string) const
-> decltype(l(body, subject))
{
return l(body, subject);
}
template<typename T>
auto call(T& l, std::string body, std::string, std::string) const
-> decltype(l(body))
{
return l(body);
}
L lambda;
};
template<typename L>
auto makeOptionalWrapper(L l) { return OptionalWrapper<L>{std::move(l)}; }
然后,使用你的包装器:
void loadData(std::function<void (std::string, std::string, std::string)> callback)
{
callback(body, subject, header);
}
template<typename L>
void loadData(L callback)
{
loadData({makeOptionalWrapper(std::move(callback))});
}
答案 2 :(得分:1)
我受到了其他一个答案的启发,它建议制作一个将正确数量的参数传递给仿函数的包装器。我发现这个解决方案非常好,并且我认为我会尝试制作一个通用模板包装器,其中参数的数量不是硬编码的。以下是我提出的建议:
{{1}}
这适用于任何函数,具有任意数量的“可选”参数以及任何类型的参数。它不是最漂亮的代码,但我希望这个想法很清楚,可以有所帮助:)