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

发布于 2024-09-30 12:11:51 字数 1181 浏览 7 评论 0原文

假设我有一个函数,它接受一个空函子作为参数:

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 被“返回”到队列中,但失败了。

我的第二次尝试如下:

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)少得令人无法接受,而且编译时开销很高。

Suppose I have a function which takes a nullary functor as an argument:

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

I have another function which takes an int and does something internally:

void foo( int a);

I would like to nest, but not compose, these together so that I get a functor with the signature:

boost::function<void(int)> functor

Which when called with a value - say 4 - performs the following:

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

My first attempt was the following:

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

This fails because bind performs composition when given a nested bind. foo was first called, then the value void was "returned" to enqueue, which fails.

My second attempt was the following:

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

This failed because enqueue accepts a nullary, not unary functor.

Can what I'm seeking be done?

Other information:

  • This is basically identical to the unanswered boost forum question from 6 years ago:
    http://lists.boost.org/boost-users/2004/07/7125.php
  • Some reading suggests that using boost::lambda::bind with boost::lambda::unlambda and boost::lambda::protect may do what I'm seeking. Unfortunately boost::lambda has an unacceptably low number of allowed placeholders (3), and high compile-time overhead.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一抹微笑 2024-10-07 12:11:51

有趣的问题...

您基本上想要的是“绑定调用绑定”。与将调用绑定到 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);});};

Interesting question...

What you basically want is a "bound call to bind". In the same manner than binding a call to foo(x, y) is written bind(&foo, x, y), binding a call to bind(&foo, x) should be like bind(&bind, &foo, x). However, taking the address of an overloaded function quickly gets ugly and, as boost::bind has more overloads than I could count, it gets pretty ugly:

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

You'll probably agree that, while "interesting", the above won't win readability contests. Separating the obtention of the proper bind overload from the rest makes things a bit more manageable:

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

but I still hesitate to recommend it ;)

Edit:

Answering the OP's comment about how/if C++0x would help to clean the syntax: It does:

auto f = [](int i){enqueue([=](){foo(i);});};
歌入人心 2024-10-07 12:11:51

手动“嵌套”:

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

'Nest' manually:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文