为什么std :: bind不能成为参数包的参数?

时间:2013-11-07 12:45:02

标签: c++ c++11 lambda functional-programming stdbind

我想使用参数包,但发现问题。 一些代码:

template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))
{
    auto f11 = std::bind(func, args...);
    f11();
}

void print(const char* string)
{
    std::cout << string << std::endl;
}

所有这些都很有效:

    f([] (const char* additional, const char* more) {
        std::cout << "hello ( " << additional << ", " << more << " )" << std::endl;
    }, "additional text", "and one more");

    auto printFunction = std::bind(&print, std::placeholders::_1);

    printFunction("hello from print bind");

    f(print, "hello from print directly");

但如果我想将std :: function赋予参数包:

f([] (std::function<void(const char*)> printParamFunc) {
 printParamFunc("hello from print from std::function");
}, printFunction);

应用程序不再编译。

那么,在pack中使用函数作为参数的问题是什么?

感谢。

更新 如果将f的代码更改为:

template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))
{
    func(args...);
}

效果很好,但是我不想在这里执行这个功能,我想创建函数并像param一样传递它。

UPDATE2: 代码执行示例:http://ideone.com/gDjnPq

UPDATE3: 清除包含编译错误的代码:http://ideone.com/50z7IN

1 个答案:

答案 0 :(得分:0)

我现在了解情况好一点。

此代码可以重新引入问题:

void print(const char* string)
{
    std::cout << string << std::endl;
}

int main(int argc, char ** argv)
{
    auto lambda = [] (std::function< void ( const char * ) > printParamFunc) {
        printParamFunc("hello from lambda!");
    };

    std::bind(lambda, std::bind(print, std::placeholders::_1))();
}

嵌套std :: bind尝试评估并失败,转换_1到const char *。它特定于std :: bind。

我们需要boost :: bind :: protect的模拟 - 存储其他函子的functor - 它解决了问题:

template <class F>
struct lazy_evaluate {
    typedef typename F::result_type T;

    explicit lazy_evaluate(F f) : f_(f) {}

    template <class... Args>
    T operator()(Args&&... args) 
    {
        f_(std::forward<Args>(args)...);
    }

private:
    F f_; 
};

template <class F>
lazy_evaluate<F> lazy(F f)
{
    return lazy_evaluate<F>(f);
}

嵌套的std :: bind现在看起来像:

std::bind(lambda, lazy(std::bind(print, std::placeholders::_1)))();

并且运作良好。