为什么从bind返回的对象会忽略额外的参数?

Kno*_*abe 19 c++ stdbind c++11

假设我有一个带两个参数的函数,

void f(int x, int y);
Run Code Online (Sandbox Code Playgroud)

我想绑定其中一个.我可以使用std::bind如下:

auto partiallyBoundF = std::bind(f, 10, _1);
Run Code Online (Sandbox Code Playgroud)

partiallyBoundF只需要一个参数,但我可以用多个参数调用它.超越第一个的论点甚至不必是一个有意义的类型:

partiallyBoundF(20, 0);
partiallyBoundF(0, 44, -99, "Hello", 4.5, true, []{});
Run Code Online (Sandbox Code Playgroud)

允许返回的对象bind传递额外参数的目的是什么?它允许编译调用错误,否则将被拒绝.

eca*_*mur 18

忽略额外的参数实现起来要简单得多,实际上可能很有用.

在典型的实现中,例如libstdc ++(g ++),所采用的方法是将operator()参数收集到元组中,然后让std::placeholder绑定参数根据需要提取它们.执行参数计数需要计算使用占位符的数量,这将非常复杂.请注意,bind callable可以是具有多个或模板化operator()调用模式的仿函数,因此operator()无法使用单个"正确"签名生成绑定对象.

另请注意,您可以写:

std::bind(&foo, std::placeholders::_1, std::placeholders::_3);
Run Code Online (Sandbox Code Playgroud)

即明确忽略绑定对象的第二个参数.如果bind强制执行其参数计数,则需要另外一种方法来指定例如第四个参数也被忽略.

至于有用性,考虑将成员信号处理程序绑定到信号:

sig.connect(std::bind(&C::on_sig, this, param, std::placeholders::_1));
Run Code Online (Sandbox Code Playgroud)

如果sig有额外的无用发射参数,则它们被bind对象简单地忽略; 否则,将相同的处理程序绑定到多个信号将需要编写多个转发包装器,而不是真正的目的.

  • "更有用" - 我会辩论.这打破了强打字.如果需要,只需使用接受可变参数的代理函数,就可以使用严格的`std :: bind`模拟这种行为. (3认同)
  • @KonradRudolph实际上,`bind`表达式的有效调用签名集在一般情况下是*不可计算的*,通过明显的构造,即使对于严格的`std :: bind`也是如此. (3认同)
  • @KonradRudolph绑定表达式在一般情况下不具有*定义良好的类型,如果它的可调用是一个带有多个`operator()的函子. (2认同)