【发布时间】:2012-03-14 00:57:09
【问题描述】:
【问题讨论】:
-
您不能直接将代码复制到帖子中吗?您是在让我们查看 24 行代码的场外源代码吗?
-
@NicolBolas 是的。你得到错误,可以克隆它,玩一下它......这在 irc://chat.freenode.net/##c++ 上被认为是正确的网络礼仪,我认为它在这里也很方便。
【问题讨论】:
问题似乎是std::bind 在内部传递Callable(实际上是std::bind<> 类型)对象c 的评估结果时间:
part2(std::bind(&Quux::part3<Callable>, this, 3, c))
它没有像您假设的那样传递 std::bind 对象的未评估版本。
因此,由于您的 f 函数返回 void 类型,c 表达式的结果在内部作为 void 类型传递,而不是未评估的可调用函数对象。因此,当您尝试在Quux::part2 中调用Callable 对象c 时,它又会尝试评估Quux::part3 中的调用c,它不能将可调用对象作为第二个参数传递给Quux::part3 ,因为它传递的类型实际上是 void 类型,而不是可调用类型。
如需进一步参考,请参阅此处:http://en.cppreference.com/w/cpp/utility/functional/bind
特别注意:
如果
std::is_bind_expression<T>::value==true(即,另一个std::bind()子表达式在对bind的初始调用中用作参数),则立即调用该绑定子表达式并传递其结果到函数。
如果您想延迟评估以便它在您希望的时候发生,而不是在您传递 std::bind 子表达式时,您将不得不寻找另一种方法,例如 lambda 或 @987654344 @ 对象、函子或一些其他类对象类型,它们既可调用又可存储可稍后评估的状态。
【讨论】:
std::bind 传递给另一个std::bind 时,会计算第一个子表达式,并将结果 传递给第二个std::bind ...所以如果你评估一个void (*)(int),你最终会得到一个void类型的结果,而不是一个可调用的void(*)(int)。尽管您没有显式调用 c,但实际上是在后台调用它,因为嵌套了 std::bind 表达式,调用的结果是传递的,而不是可调用对象本身。