【问题标题】:Why is this std::bind not converted to std::function?为什么这个 std::bind 没有转换为 std::function?
【发布时间】:2012-11-28 22:53:41
【问题描述】:

为什么以下代码中的嵌套std::bind 没有被任何主要编译器(VS2010/2012、gcc、clang)隐式转换为std::function<void()>?这是标准行为还是错误?

#include <functional>

void bar(int, std::function<void()>) { }
void foo() { }

int main()
{
    std::function<void(int, std::function<void()>)> func;
    func = std::bind(bar, 5, std::bind(foo));

    std::cin.get();
    return 0;
}

【问题讨论】:

  • 因为嵌套的绑定表达式被急切地求值。实际上,您正在做类似于std::bind(bar, 5, void) 的事情,这是荒谬的。
  • 这并不能回答问题,但这个:func = std::bind(bar, 5,foo); 按您的预期工作。
  • 你想要达到什么目的? bar 可以直接分配给func,通过绑定参数,您正在创建一个可以在没有参数(或任何组合或参数)的情况下调用的函子。使用当前代码(假设已编译)func 必须使用 int 和 std::function&lt;void()&gt; 调用,这两个参数都将被忽略,这将触发 bar(5,foo) 的执行...
  • 我意识到这个例子在功能上是错误的,但它显示了我所询问的编译器错误。

标签: c++ function templates c++11 bind


【解决方案1】:

这在boost documentation中有解释:

内部绑定表达式以未指定的顺序被计算,在 调用函数对象时的外部绑定;的结果 然后当外部绑定被替换时,评估被替换为 评估。在上面的例子中,当函数对象被调用时 使用参数列表 (x),首先评估 bind(g, _1)(x), 产生 g(x),然后对 bind(f, g(x))(x) 求值,产生 最终结果 f(g(x))。

Boost 甚至提供了protect 来防止这种评估:

#include <boost/bind/protect.hpp>
...
func = std::bind(bar, 5, boost::protect(std::bind(foo)));

但是,要调用func,您必须像这样提供两个参数(感谢David Rodríguez - dribeas 指出),所以这个例子肯定不好:

func(1, std::function<void()>());

【讨论】:

  • boost::protect 和 std::bind 一起玩好吗?我没试过,但我认为他们不会......
  • @ildjarn: boost::protect 真的没什么特别的,它只是一个完美的转发函子,如果你愿意的话。特殊的是std::bind 的返回类型,std::is_bind_expression 为真。根据该特征,函子要么被热切地评估,要么只是正常传递。对于boost::protect 的结果,is_bind_expression 派生自false_type。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2017-04-22
  • 2020-10-28
相关资源
最近更新 更多