在没有组合的情况下对嵌套的boost :: bind执行参数替换

时间:2010-11-03 20:53:20

标签: c++ boost boost-bind functor

假设我有一个以nullary仿函数为参数的函数:

void enqueue( boost::function<void()> & functor );

我有另一个函数,它接受一个int并在内部做一些事情:

void foo( int a);

我想将这些一起嵌套,但不要编写,以便我得到一个带签名的仿函数:

boost::function<void(int)> functor

当使用值调用时 - 例如4 - 执行以下操作:

enqueue( boost::bind(&foo, 4) )

我的第一次尝试如下:

boost::function<void(int)> functor = boost::bind(&enqueue, boost::bind(&foo,_1))

这会失败,因为绑定在给定嵌套绑定时执行合成。 foo首先被调用,然后值void被“返回”到入队,但是失败了。

我的第二次尝试如下:

boost::function<void(int)> functor = boost::bind(&enqueue, boost::protect( boost::bind(&foo, _1) ) )

这失败了,因为enqueue接受了一个假的,而不是一元的函子。

我正在寻找的是什么?

其他信息:

  • 这与6年前未答复的提升论坛问题基本相同: http://lists.boost.org/boost-users/2004/07/7125.php
  • 一些阅读建议使用boost :: lambda :: bind与boost :: lambda :: unlambda和boost :: lambda :: protect可以做我想要的。不幸的是,boost :: lambda允许的占位符数量低得令人无法接受(3),并且编译时开销很高。

2 个答案:

答案 0 :(得分:4)

有趣的问题......

你基本上想要的是“绑定绑定”。以与绑定foo(x, y) bind(&foo, x, y)的约束相同的方式,绑定对bind(&foo, x)的调用应该与bind(&bind, &foo, x)类似。但是,获取重载函数的地址很快就会变得很丑陋,因为boost::bind的重载次数超出了我的计算范围,所以它变得非常难看:

// One single line, broken for "readability"
boost::function<void(int)> f = boost::bind(
  &enqueue, 
  boost::bind(
    static_cast<
      boost::_bi::bind_t<
        void, void(*)(int), boost::_bi::list_av_1<int>::type
      >
      (*)(void(*)(int), int)
    >(&boost::bind), 
    &foo, 
    _1
  )
);

你可能会同意,虽然“有趣”,但上述内容不会赢得可读性竞赛。将正确的绑定重载与其他绑定的分离分开会使事情更容易管理:

boost::_bi::bind_t<void, void(*)(int), boost::_bi::list_av_1<int>::type>
  (*bind_foo)(void(*)(int), int) = &boost::bind;

boost::function<void(int)> q = boost::bind(&enqueue, boost::bind(bind_foo, &foo, _1));

但我仍然犹豫推荐它;)

修改

回答OP关于如何/如果C ++ 0x有助于清除语法的评论:它确实:

auto f = [](int i){enqueue([=](){foo(i);});};

答案 1 :(得分:0)

手动

'Nest':

class Enqueuer {
 std::function<void (int)> mFunc;

public:
 void operator()(int pVal) {
  enqueue(std::bind(mFunc, pVal));
 }

 Enqueuer(std::function<void (int)> pFunc)
  : mFunc(pFunc) {}
};

// usage:
Enqueuer e(foo);
e(1);
e(2);
e(3);