std :: function объекты могут быть скопированы
std::function
- это объект стирания типа, который поддерживает копирование сохраненного объекта.
Когда вы храните std::unique_ptr
в лямбде, эта лямбда не поддерживает копирование.
Так что std::function
вполне справедливо жалуется. Это тип, который можно скопировать, и когда передается что-то, выясняется, как его скопировать. «Я не могу скопировать это» не является правильным ответом; все std::function
s могут быть скопированы.
Промышленное решение для прочности:
Существует два распространенных подхода к решению этой проблемы. Во-первых, вы сохраняете состояние std::function
в некотором виде std::shared_ptr
. Во-вторых, вы пишете или находите не копирующий std::function
и используете его вместо этого.
Более "современные" std::function
библиотеки замены поддерживают ряд полезных вещей:
- представления функций, которым не принадлежит то, что они переносят.
- Функциональные объекты только для перемещения, которые не поддерживают копирование.
- Объекты с множественной перегрузкой, которые поддерживают более 1 подписи одновременно.
- буферы фиксированного размера, которые не компилируются, если не хватает автоматического хранилища вместо выделения кучи.
- тривиально копируемые функциональные объекты
Я лично нуждался в каждом из вышеперечисленных для различных специальных целей.
Тогда вы будете использовать moveonly_function<void()>
, когда вам не нужно копировать вызываемый объект, и ваш код компилируется.
Однако сейчас это, вероятно, слишком тяжело для ваших нужд.
Быстрое решение:
template<class F>
auto make_shared_function( F&& f ) {
return
[pf = std::make_shared<std::decay_t<F>>(std::forward<F>(f))]
(auto&&...args)->decltype(auto)
{
return (*pf)( decltype(args)(args)... );
};
}
теперь, когда вы сталкиваетесь с этой проблемой:
// This does not compile.
std::function<void()> func = make_shared_function([p = move(ptr)] { });
и состояние вызываемого объекта теперь сохраняется в общем ptr.