9

我正在玩 std::function 和 std::bind ,我注意到一些不直观的东西,我想更好地理解它。

例如:

void fun()
{
}

void hun(std::string) 
{ 
}

int main()
{

   function<void(int)> g = &fun; //This fails as it should in my understanding.

   function<void(int)> f = std::bind(fun); //This works for reasons unknown to me     
   function<void(int, std::string)> h = std::bind(hun); //this doesn't work

return 0;
}

如何将 a 绑定function<void(int)>void()函数。然后我可以调用 f(1) 并获得 fun()。我想了解这是如何完成的。深入 Microsoft Visual Studio 2012 的实现让我迷失在无法阅读的宏的海洋中。所以这就是我在这里问这个问题的原因。

4

2 回答 2

8

如果您不使用参数占位符 ( _1, _2, ...),则传递给从返回的函数对象的任何参数std::bind都将被丢弃。和:

std::function<void(int)> f = std::bind(fun, std::placeholders::_1);

正如预期的那样,我得到了一个(又长又丑的)错误。

对于对标准语感兴趣的人:

§20.8.9.1.2 [func.bind.bind]

template<class F, class... BoundArgs>
*unspecified* bind(F&& f, BoundArgs&&... bound_args);

p3 返回:g具有弱结果类型 (20.8.2) 的转发调用包装器。的效果g(u1, u2, ..., uM)应该是INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type),其中cv表示 的cv 限定符g 绑定参数的值和类型v1, v2, ..., vN按以下规定确定

p10 绑定参数的值v1, v2, ..., vN及其对应的类型V1, V2, ..., VN 取决于TiD从调用派生bind的类型和调用包装器的cv -qualifiers cvg ,如下所示:

  • 如果TiDreference_wrapper<T>,参数是tid.get(),它的类型ViT&
  • 如果 的值为 ,is_bind_expression<TiD>::valuetrue参数为tid(std::forward<Uj>(uj)...),其类型Viresult_of<TiD cv (Uj...)>::type
  • 如果 的值jis_placeholder<TiD>::value为零,则参数为std::forward<Uj>(uj)且其类型ViUj&&
  • 否则,值为tid,其类型ViTiD cv &
于 2013-04-23T08:56:37.123 回答
6

调用函数模板生成的转发调用包装器bind可以接受任意数量的额外参数;这些将被忽略。bind表达式的有效数量和最小签名placeholder由其构造中使用的 s 以及它们绑定到的可调用参数确定。

于 2013-04-23T09:00:39.213 回答