Здравствуйте, Аноним, Вы писали:
А>Объясните, пожалуйста, почему следующий код не компилируется?
Потому что конструкция из вложенных биндов — это не замыкание с замыканием, а одно большое замыкание.
(Потому что std::bind — не просто функция высшего порядка, но ещё и конструктор Expression Template).
Если внутрений бинд отдельно скопировать в function, то он будет изолирован от внешнего.
Чтобы изолировать по месту, достаточно написать boost::protect
std::thread th(std::bind(foo, std::bind(callback_function, 0, 1.0)));
// эквивалентно
std::thread th(
[]()
{
foo(callback_function(0, 1.0));
}
);
std::thread th(std::bind(foo, boost::protect(std::bind(callback_function, 0, 1.0))));
// эквивалентно
std::thread th(
[]()
{
foo(
[]() { callback_function(0, 1.0); }
);
}
);
Почему-то в 11 стандарт boost::protect не попал, поэтому нужно или подключить буст, или написать вручную
template<class T>
struct protector
{
T t;
protector(T const& t) : t(t) {}
protector(T&& t) : t(t) {}
template<class... A>
auto operator()(A... a) -> decltype(t(a...)) const { return t(a...); }
};
template<class T> protector<T> protect(T&& t) { return protector<T>(t); }
Но, поскольку foo всё равно принимает std::function, то можно вместо protect прямо написать
std::thread th(std::bind(foo, std::function<void()>(std::bind(callback_function, 0, 1.0))));
Или, раз мы всё равно в 11 стандарте, написать лямбдами. С ними, как мне кажется, это и нагляднее будет.