询问boost :: bind()的限制示例

时间:2012-02-06 02:53:00

标签: c++ boost

我读了限制的解释 http://www.boost.org/doc/libs/1_49_0/libs/bind/bind.html#Limitations 但我不太明白。 请问任何机构能给我一个例子吗?

让我用这个例子以另一种方式提出这个问题:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <string>
using namespace std;

void Five(int &a, int &b, int &c, const int &d, const int &e) {
  cerr << "In Five(): " << a + b + c + d + e << endl;
}

int main() {
  int r = 1;
  const int c = 100;

  boost::bind(Five, _1, _2, _3, _4, _5)(r, r, r, c, r);
  boost::bind(Five, _1, _2, _3, _4, _5)(r, r, r, r, c);

  return 0;
}

这段代码编译得很好(没有C ++ 11支持)。那么,如果绑定在这种情况下工作,那么“限制”是指什么?有什么具体的例子吗?

另一个(更好)的例子:

#include <boost/bind.hpp>
#include <iostream>
#include <string>
using namespace std;

void Two(int &a, const int &c) {
  cerr << "In Two(): " << a + c << endl;
}

void Three(int &a, int &b, const int &c) {
  cerr << "In Three(): " << a + b + c << endl;
}

int Fun() { return 3; }

int main() {
  int r = 1;
  const int c = 100;
  boost::bind(Two, _1, _2)(r, Fun());           // 1. OK
  boost::bind(Three, _1, _2, _3)(r, r, c);      // 2. OK
  Three(r, r, Fun());                           // 3. OK
  boost::bind(Three, _1, _2, _3)(r, r, Fun());  // 4. CE!!
  //??? Why 2 is OK but 4 is not ???

  return 0;
}

2 个答案:

答案 0 :(得分:2)

限制是指&#34;完美转发&#34;,它是通过启用c ++ 0x在最近的编译器上实现的(在编译时可能需要一些选项)。

如果编译器支持c ++ 0x,那么boost :: bind使用完美转发,否则忽略问题以避免函数重载爆炸!

例如:当使用2个参数绑定一个函数时,boost :: bind创建的仿函数对象将需要所有这些重载(如果没有c ++ 0x支持):

operator()(const A&, const B&)
operator()(const A&, B&)
operator()(A&, const B&)
operator()(A&, B&)

完美地前进。

这是一个详细描述完美转发问题的链接:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm

不完美的转发将最终导致您:

  • 非const或const引用解决方案(如boost :: bind)
  • 的编译错误
  • 在按值解决方案的情况下出现意外副本

答案 1 :(得分:0)

想象一下,你有以下泛型函数(它只是传递参数(称为“转发”)到内部函数callme):

template <typename T> void f(T& t)
{
    callme(t);
}

现在,假装callme的定义如下:void callme(const int& i)。 问题是callme(1)可以工作,但f(1)不会(这是因为rvalues不绑定到非const引用)。要解决此问题,您需要将f更改为:f(const T& t)。 但是,这引入了一个新问题。如果callme定义如下:void callme(int& i),则会出现编译错误。解决方案是为f设置两个重载,以同时使用f(const T& t)f(T& t)

现在,当函数只接受一个参数时,上述情况正常。但是,想象一个带有两个参数的函数,你必须进行4次重载:

f(const T1&, const T2&)
f(const T1&, T2&)
f(T1&, const T2&)
f(T1&, T2&)

In this article on msdn,它提到对于tr1::bind,对于5个参数,总共需要63次重载! 我刚刚解释的内容称为forwarding problem,它已使用完美转发和右值引用在C++11中解决。

Boost网站引用:

The library chooses a small subset: for up to two arguments, it provides the const overloads in full, for arities of three and more it provides a single additional overload with all of the arguments taken by const reference.