如何调用绑定了所有参数的 boost::function 对象

How to call a boost::function object with all arguments bound

我在 boost::functionboost::bindreading up,但是,我似乎无法弄清楚 "good way" 调用 boost 函数,如果所有参数都被绑定(我认为这是正确的术语)。下面是一个未经测试的 MCVE(复制粘贴我的真实代码并不理想)。

#include "boost/function.hpp"
#include "boost/bind.hpp"
#include <iostream>

void func(void* args)
{
  int* myInt = static_cast<int*>(args);
  if (myInt != NULL)
  {
    std::cout << "myInt = " << *myInt << std::endl;
  }
  else
  {
    std::cout << "args is NULL" << std::endl;
  }
}

int main()
{
  int myInt1 = 5;
  int myInt2 = 45;

  boost::function<void(void* args)> myFunc = boost::bind(&func, &myInt1);

  // here's my problem,, how do I call myFunc?
  myFunc();  // this does not compile due to missing arguments
  myFunc;    // this is essentially a no-op. The function doesn't execute,
             // and if I put a breakpoint here, it either goes to the next
             // line or I get a warning that no executable code exists here

  // after some experimentation, I realized I can do this and it works
  myFunc(NULL);  // this prints out "myInt = 5"

  // this also prints out "myInt = 5"
  boost::bind(&func, &myInt1)();

  // finally, this prints out "myInt = 5" as well
  myFunc(&myInt2);

  return 0;
}

所以我的问题是,调用 myFunc 的 preferred/right 方法是什么?我已经通过传入适当的参数成功地调用了带有 _1_2 等参数占位符的函数。也许在实践中几乎所有时间都有占位符? myFunc(NULL) 有效,但对我来说这似乎很愚蠢,如果我已经绑定了它们(并且我传递的内容无论如何都无关紧要),我基本上必须编造论据。在我的真实代码中,我实际上想在不同的函数中调用 myFunc(所以 boost::bind(&func, &myInt1)(); 不是一个选项),我在 class 的对象中这样做,所以我希望我提供的示例表现出与我在真实代码中看到的相同的行为。我用的是Visual Studio 2013,不能用c++11以后的版本。

具有 "all parameters bound" 的函数对象没有参数,因此其类型为 boost::function<void()>。你需要

boost::function<void()> myFunc = boost::bind(&func, &myInt1);

myFunc 变量的更好类型是 boost::function<void()>,因为原始 func 的所有参数都已绑定,调用生成的包装器实际上不需要任何参数。

boost::function<void()> myFunc = boost::bind(&func, &myInt1);

这实际上允许您调用该函数:

myFunc();

但是编译器允许 boost::function<void(void*)> 类型的原因是 boost::bind 调用的结果可以用比必要更多的参数调用,如果你选择的话,额外的参数将被忽略.这样做的一件事是让这样的情况更加一致:

void f(int, int);
// g1 acts the same as f:
boost::function<void(int, int)> g1 = boost::bind(f, _1, _2);
// g2 swaps the order of arguments when calling f:
boost::function<void(int, int)> g2 = boost::bind(f, _2, _1);
// g3 ignores its first argument and passes the second to f twice:
boost::function<void(int, int)> g3 = boost::bind(f, _2, _2);
// g4 ignores its second argument and passes the first to f twice:
boost::function<void(int, int)> g4 = boost::bind(f, _1, _1);

g4 初始化中,我们可以说 bind 表达式只是另一个可以用两个 int 参数调用的绑定函数,因为它不使用任何位置大于 2 的占位符。它也可以只用一个参数调用,因为 _2 本身也从未使用过,但这并不会使上述错误。

同样,在您初始化 boost::function<void(void*)> 的代码中,编译器接受完全绑定的 bind 表达式作为可以用一个参数有效调用的东西,因为它不使用任何占位符位置大于 1。虽然实际上它也不使用位置正好为 1 的占位符 _1,但以这种方式使用时 void* 输入最终会被忽略。