c ++ 0x std :: function в качестве аргумента метода - PullRequest
7 голосов
/ 27 октября 2011

Я пытаюсь передать std :: function через метод, подобный так:

class dispatch
{
  public:
     deliver( std::function<void ( void )> task );
}

Это работает, как и ожидалось.Однако я хочу передать аргументы некоторым методам, поставляемым в качестве задачи, но предпочел бы не создавать перегрузки для всех различных форм функций <...>.

Например, это вообще возможно простосоздать метод, подобный следующему

deliver( std::function& task );

и просто вызвать с помощью

dispatch->deliver( bind( &Object::method, X ) );

или

dispatch->deliver( bind( &Object::method, X, arg1, arg2 ) );

и т.д ...

Спасибо закаждый вход.Похоже, моя настоящая ошибка в вызовах dispatch-> delivery с дополнительным аргументом, также являющимся вызовом bind.

dispatch->deliver( bind( &Object::method1, X1, bind( &Object::method1, X2 ) );

ошибка: / usr / include / c ++ / v1 / functions: 1539: 13: ошибка: нет соответствующей функции для вызова '__mu_expand', возврата __mu_expand (__ti, __uj, __indices ());

Ответы [ 3 ]

10 голосов
/ 27 октября 2011

std::function<void(void)> уже полиморфна, вот и весь смысл.Таким образом, эти два последних фрагмента будут работать (до тех пор, пока функция functor bind может быть вызвана без аргументов и, конечно, ничего не возвращает), без изменения того, что у вас уже есть.

3 голосов
/ 27 октября 2011

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

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <list>
#include <string>

typedef boost::function<void(void)> fun_t;
typedef std::list<fun_t> funs_t;

void foo()
    { std::cout <<"\n"; }
void bar(int p)
    { std::cout<<"("<<p<<")\n"; }
void goo(std::string const& p)
    { std::cout<<"("<<p<<")\n"; }

void caller(fun_t f)
    { f(); }

int main()
{
    funs_t f;
    f.push_front(boost::bind(foo));
    f.push_front(boost::bind(bar, int(17)));
    f.push_front(boost::bind(goo, "I am goo"));

    for (funs_t::iterator it = f.begin(); it != f.end(); ++it)
    {
        caller(*it);
    }

    return 0;
}

(Обратите внимание, я использую Boost.Function и Boost.Bind, но не должно быть никакой разницы в использованииstd :: bind и std :: function.)

1 голос
/ 28 октября 2011
class dispatch
{
  public:
     template <typename ... Params>
     deliver( std::function<void (Params && p...)> task, Params && p )
     {
         task(std::forward(p)...);
     }
};

Я не скомпилировал это (исправления приветствуются!), Но идея должна работать.

dispatch->deliver( bind( &Object::method, X ) );
dispatch->deliver( bind( &Object::method, X, arg1, arg2 ) ); // OR!
dispatch->deliver( bind( &Object::method, X ), arg1, arg2 );

Единственное, что мне неясно, это как себя вести, если Object::method имеет параметры по умолчанию вместо перегрузок.

...