如何将前N个args传递给C ++函数

时间:2017-10-16 17:39:04

标签: c++11 lambda c++14 variadic-functions generic-lambda

我有这样的功能:

void loadData(std::function<void (std::string, std::string, std::string)> callback)
{
    // data loading stuff
    callback(body, subject, header);
}

问题是我不一定需要在回调函数中使用subjectheader。现在我正以这种方式处理它:

loadData([](std::string body, std::string, std::string){
    std::cout << body;
})

我想用

替换它
loadData([](std::string body){
    std::cout << body;
})

并自动传递给回调函数尽可能多的参数。 我不想为所有3个可能的参数计数手动重载loadData函数。我也不想在调用站点上使用任何更复杂的lambda语法,因为我的库应该清楚,供其他人使用。 这可能是使用C ++ STL和Boost吗?

3 个答案:

答案 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}}

这适用于任何函数,具有任意数量的“可选”参数以及任何类型的参数。它不是最漂亮的代码,但我希望这个想法很清楚,可以有所帮助:)

Live example