4

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がエンキューに「返され」ましたが、これは失敗します。

私の2番目の試みは次のとおりです。

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

enqueueは単項ファンクターではなく、nullaryを受け入れるため、これは失敗しました。

私が求めていることはできますか?

その他の情報:

  • これは基本的に、6年前の未回答のブーストフォーラムの質問と同じです: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));

しかし、私はまだそれをお勧めすることを躊躇します;)

編集:

C ++0xが構文をクリーンアップするのにどのように役立つかについてのOPのコメントに答える:それは:

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 に答える