std::bind of std::bind
От: steep8  
Дата: 17.09.15 13:41
Оценка:
Имеется нечто вроде такого:

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));
что то пока не понятно как внешнюю таску затолкать во враппер.
Re: std::bind of std::bind
От: Caracrist https://1pwd.org/
Дата: 17.09.15 15:25
Оценка:
Здравствуйте, steep8, Вы писали:

    service_.post(std::bind(&Sheduler::wrapTask<Task>, this, task));
~~~~~
~lol~~
~~~ Single Password Solution
Re: std::bind of std::bind
От: _NN_ www.nemerleweb.com
Дата: 17.09.15 18:29
Оценка: +1
Здравствуйте, steep8, Вы писали:

Раз есть std::bind может проще лямбдой ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: std::bind of std::bind
От: Кодт Россия  
Дата: 21.09.15 15:47
Оценка:
Здравствуйте, 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); } );
Перекуём баги на фичи!
Re[2]: std::bind of std::bind
От: Abyx Россия  
Дата: 21.09.15 20:02
Оценка: +1
Здравствуйте, Кодт, Вы писали:

К>service.post( [=this] () { this->wrapTask(task); } );


[=this] это неправильный синтаксис, там правила вида "[" ("this" | "&" | "=" | identifier | "&" identifier | ...) "]"
т.е. this это особый случай, и вообще [=identifier] не бывает
In Zen We Trust
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.