У меня есть функция отправки, которая выполняет данную лямбду в главном потоке. Ради этого вопроса предположим, что это выглядит следующим образом:
void dispatch(const std::function<void()>& fn) {
fn();
}
Мне нужно загрузить новый объект в новом потоке, не прерывая основной поток. Поэтому я делаю следующее: 1) запускаю новый поток и создаю новый уникальный указатель внутри потока, 2) вызываю dispatch
и распространяю новый уникальный указатель там, где он принадлежит.
std::unique_ptr<std::string> foo; // nullptr
// do the loading in a new thread:
std::thread t([&](){
// in the new thread, load new value "Blah" and store it temporarily
auto bar = std::make_unique<std::string>("Blah");
dispatch([bar2 = std::move(bar), &foo]() mutable {
foo = std::move(bar2); // propagate the loaded value to foo
});
});
t.join(); // for the sake of this example
std::cout << "foo = " << *foo << std::endl; // this should say: foo = Blah
Запустить пример онлайн: http://cpp.sh/5zjvm
Этот код не компилируется, потому что внутренняя лямбда в dispatch
равна mutable
и поэтому не вписывается в dispatch(const std::function<void()>& fn)
, для которого требуется const&
.
Однако лямбда должна быть mutable
, потому что она должна вызывать std::move
для уникальных указателей.
Этот код можно исправить, например, изменив dispatch
на:
template <typename Fn>
void dispatch(Fn fn) {
fn();
}
К сожалению, функция dispatch
является API библиотеки, и я не могу ее изменить.
Есть ли выход из этой проблемы без избавления от уникальных указателей?