Имеется нечто вроде такого:
class Sheduler {
public:
template <class Task>
void runTask(Task) {
service_.post(std::bind(&Sheduler::wrapTask, this, task));
}
template <class Task>
void wrapTask(Task task) {
task();
}
boost::asio::io_service service_;
};
Class Worker {
public:
void process(int param) {
....
}
};
void main() {
Worker worker;
Sheduler sheduler;
sheduler.runTask(std::bind(&Worker::process, &worker, 128);
};
Не компилируется на строчке service_.post(std::bind(&Sheduler::wrapTask, this, task));
что то пока не понятно как внешнюю таску затолкать во враппер.
Здравствуйте, steep8, Вы писали:
service_.post(std::bind(&Sheduler::wrapTask<Task>, this, task));
Здравствуйте, steep8, Вы писали:
S>Не компилируется на строчке service_.post(std::bind(&Sheduler::wrapTask, this, task));
S>что то пока не понятно как внешнюю таску затолкать во враппер.
std::bind — это сахарная функция, интеллектуальные скобки. Для вложенных bind'ов они прозрачны.
То есть, получается выражение
auto somefun = bind(&Sheduler::wrapTask<Task>, this, bind(&Worker::process, &worker, 128));
// где-то когда-то позже делается вызов
somefun();
// эквивалентно
this->wrapTask(worker.process(123));
То есть, во wrapTask передаётся не замыкание, а результат!
Равно как, скажем,
auto somefun = bind(foo, _1, bind(bar, _1));
somefun(123)
// эквивалентно
foo(123, bar(123))
Для того, чтобы bind не лез внутрь вложенного bind, а передавал замыкание как есть, нужно изолировать его. К сожалению, в стандарте такой функции нет, зато она всё ещё есть в бусте, откуда bind и приехал.
Называется boost::protect.
Это легковесное (в отличие от boost/std::function) замыкание, НЕ ЯВЛЯЮЩЕЕСЯ bind'ом — и поэтому внешний bind даже не пытается применить к нему магию для распотрашивания.
Можно выдрать из буста. Можно написать и свой аналог. На вариадиках, или для конкретной арности (void->void) так вообще плёвое дело
template<class F> struct protector {
F&& fun_;
//template<class... Args> auto operator()(Args&&... args) -> decltype(fun_(args...)) { return fun_(args...); };
void operator()() const { fun_(); }
};
template<class F> auto protect(F&& f) -> protector<F> { return protector<F>(f); }
Ну и, как уже верно заметили, — лямбды лишены этого недостатка. Да и более выразительны.
auto task = [&worker] () { worker.process(128); };
...
service.post( [=this] () { this->wrapTask(task); } );