как объединить 2 независимых boost :: bind () в одну boost :: function? - PullRequest
3 голосов
/ 27 января 2012

У меня есть 2 функции f() и g(). Я хочу каждый раз вызывать их по порядку. Могу ли я получить boost::function для этого? Например. что-то вроде:

boost::function functor = boost::bind( boost::bind(f), boost::bind(g) );

Расширьте это далее, скажем, что нужны аргументы, тогда мне нужна цепь ответственности. Каждый узел что-то делает с аргументами, затем следует следующий узел цепочки. Как мне это сделать?


Обновление Спасибо за комментарии Сета Карнеги. Я думаю, что я действительно хочу, как построить цепочку ответственности в один boost::function, каждый узел цепочки может быть построен с использованием boost::bind().

Ответы [ 3 ]

2 голосов
/ 27 января 2012

Рассматривали ли вы использование boost :: signal ?

С boost :: signal вы можете соединить несколько вызовов функций в один.

#include <boost/signal.hpp> 
#include <iostream> 

void f() 
{ 
  std::cout << " Hello" << std::flush; 
} 

void g() 
{ 
  std::cout << " World" << std::endl; 
} 

int main() 
{ 
  boost::signal<void ()> s; 
  s.connect(f); 
  s.connect(g); 
  s(); 
} 
1 голос
/ 20 января 2015

Существует довольно простое решение, использующее boost :: lambda с оператором запятой. В моем случае я использую ее для функции-модификатора, которая определяется как (B - произвольный класс, например, и A - это класс, который должен быть изменен, но находится в B и не должен выходить за пределы)

void B::modify( boost::function<void(A&)> func );

Мое намерение состоит в том, чтобы передать в модификатор только модификатор, который облегчает управление при его модификации (например, для испускания сигналов).

Иногда я хочу применить 2 модификатора:

void A::setInvalid();
void A::setX( int x );

Вызов в 2 шага, что не так (просто как ссылка, чтобы показать, как мы хотим использовать метод модификации):

instanceA->modify( 
    boost::bind( &A::setInvalid, _1 );
instanceA->modify( 
    boost::bind( &A::setX, _1, 4 );

Используя boost :: lambda, это можно объединить с одним вызовом функции, и поэтому создается только одна функция:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
instanceA->modify(
    ( bind(&A::setInvalid, boost::lambda::_1)
    , bind(&A::setX, boost::lambda::_1, 4) ) );

По вашему вопросу это будет выглядеть так:

using namespace boost::lambda;
boost::function<void()> func = ( bind(f), bind(g) )
1 голос
/ 27 января 2012

Почему бы не что-то подобное?

#include <functional>

template <typename FirstFunctor, typename SecondFunctor>
void chainFunctionImpl(FirstFunctor first, SecondFunctor second)
{
   first();
   second();
}

template <typename FirstFunctor, typename SecondFunctor>
std::function<void(void)> chainFunction(FirstFunctor first, SecondFunctor second)
{
   return std::bind(chainFunctionImpl<FirstFunctor,SecondFunctor>,first,second);
}

Использование должно быть относительно простым, просто связать функции в последовательности, а затем вызвать результат. Теоретически любая длина функций может быть соединена в цепочку.

Обратите внимание, что теоретически возможно сделать это и путем передачи аргумента по цепочке, но этот уровень шаблона foo далеко за пределами моего понимания. http://ideone.com/Xvp5U - вот где я сдался.

...