4

假设我有一个以空函子作为参数的函数:

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))

这失败了,因为 bind 在给定嵌套绑定时执行组合。首先调用 foo ,然后将值 void “返回”到 enqueue,但失败了。

我的第二次尝试如下:

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

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

我所寻求的可以完成吗?

其他信息:

  • 这与 6 年前未回答的 boost 论坛问题基本相同:http: //lists.boost.org/boost-users/2004/07/7125.php
  • 一些阅读表明,将 boost::lambda::bind 与 boost::lambda::unlambda 和 boost::lambda::protect 一起使用可能会满足我的要求。不幸的是 boost::lambda 的允许占位符 (3) 数量少得令人无法接受,而且编译时开销也很高。
4

2 回答 2

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);});};
于 2010-11-04T20:40:31.457 回答
0

手动“嵌套”:

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);
于 2010-11-04T07:45:11.777 回答