【问题标题】:Why std::bind can't be param of parameters pack?为什么 std::bind 不能作为参数包的参数?
【发布时间】:2013-11-19 02:55:37
【问题描述】:

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

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...);
}

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

更新 2: 代码执行示例:http://ideone.com/gDjnPq

更新3: 清除编译错误代码:http://ideone.com/50z7IN

【问题讨论】:

  • 然后添加最重要的部分。尝试破译它并阅读它想说的内容。如果没有错误,没有人可以帮助您。
  • 你能把sscce.org放在ideone之类的东西上并添加一个链接,以便我们可以看到生成的错误消息吗?
  • 如果不是auto,你可以让它工作,给printFunction输入std::function&lt;void(const char*)&gt;。我不知道这是为什么。来自 clang 的错误消息表明它无法推断出 _Result 类型的绑定表达式。
  • 这里是上面的一个 sscce:ideone.com/50z7IN -- 我还不知道为什么它不能编译,但它就是!
  • Answer is here一些具体的std::bind。

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


【解决方案1】:

我现在对情况有了一些了解。

此代码可以追溯问题:

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 的类比——存储其他函子的函子——这是解决问题:

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)))();

而且效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多