【问题标题】:Why do objects returned from bind ignore extra arguments?为什么从 bind 返回的对象会忽略额外的参数?
【发布时间】:2012-10-26 11:04:45
【问题描述】:

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

void f(int x, int y);

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

auto partiallyBoundF = std::bind(f, 10, _1);

partiallyBoundF 只接受一个参数,但我可以用多个参数调用它。第一个以外的参数甚至不必是任何有意义的类型:

partiallyBoundF(20, 0);
partiallyBoundF(0, 44, -99, "Hello", 4.5, true, []{});

允许从bind 返回的对象传递额外参数的目的是什么?它允许编译调用错误,而这些错误会在其他任何地方被拒绝。

【问题讨论】:

  • 什么编译器?我猜这可能只是一个不符合标准的编译器(因为允许这些额外的参数真的没有意义,我怀疑标准是否允许这样做)。例如,MSVC 通过定义每个可变参数模板来模拟可变参数模板以获取最大可能的模板参数并将它们默认为某些 NIL 类型。也许类似的事情是你行为的原因?
  • @ChristianRau:这是标准的一部分。它也是 TR1 的一部分。 20.8.2/4 评论说,预期的实现是针对可变参数模板化的 operator() 简单地接受传递给它的任何内容,而不管参数的类型或数量如何。 TR1 有类似的措辞。
  • 在您的情况下,f(w1, ..., wN) where N = sizeof...(bound_args)(绑定调用的参数数)应为有效表达式,请参见 20.8.9.1.2/2 和 20.8 .2/1。编辑:它不允许任何其他方式调用它。
  • @KnowItAllWannabe 它允许采用“任意参数列表”,但“将参数传递给包装的可调用对象”。我认为这是否允许这种调用是有争议的(毕竟f(int, double, whatever) 是无效的)。
  • @ChristianRau:带有 11 月 CTP 的 MSVC11 毫无怨言地接受了额外的参数。

标签: c++ c++11 stdbind


【解决方案1】:

忽略额外的参数实现起来要简单得多,而且实际上很有用。

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

还要注意你可以写:

std::bind(&foo, std::placeholders::_1, std::placeholders::_3);

即显式忽略绑定对象的第二个参数。如果bind 强制执行其参数计数,您将需要另一种方法来指定它,例如第四个参数也应该被忽略。

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

sig.connect(std::bind(&C::on_sig, this, param, std::placeholders::_1));

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

【讨论】:

  • “更有用”——我会对此进行辩论。这打破了强类型。如果需要,这种行为仍然可以通过严格的std::bind 来模拟,只需使用接受可变参数的代理函子即可。
  • 您可以使用 lambda 忽略第四个参数。不过不是很好。
  • @KonradRudolph 事实上,bind 表达式的有效调用签名集在一般情况下是不可计算的,通过明显的构造,即使对于严格的@ 987654333@.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 2015-01-13
  • 1970-01-01
相关资源
最近更新 更多