Почему я не могу переместить элемент в вектор не копируемых объектов?

Компилятор говорит мне, что я пытаюсь получить доступ к удаленной функции (то есть конструктору копирования лямбда-выражения). Но я не вижу, где.

std::vector<std::function<void()>> tasks;
std::packaged_task<int()> task{ [] { return 1; } };
tasks.emplace_back(
    [ t = std::move(task) ] () mutable { t(); });

( код также находится здесь )

(я пытаюсь выяснить, почему они используют shared_ptr<task> в https://www.slideshare.net/GlobalLogicUkraine/c11-multithreading-futures ).

На Gcc и MSVC я получаю одну и ту же ошибку - боюсь, я что-то не так делаю ...

error: use of deleted function 
'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'

Почему я не могу вставить это std::function в вектор?

7 голосов | спросил xtofl 6 J0000006Europe/Moscow 2017, 10:32:43

3 ответа


0

Из cppreference :

  

F должен соответствовать требованиям Callable и CopyConstructible

Где F - это тип функции, используемый для построения std::function. Однако std::packaged_task является не копируемый конструктив . Таким образом, в списке захвата t не является копируемым конструктором и является нестатическим членом лямбда-выражения, что делает неявный конструктор копирования для лямбда удалена.

ответил Weak to Enuma Elish 6 J0000006Europe/Moscow 2017, 11:04:18
0

Краткий ответ: лямбды и std::packaged_task не являются std::function s.

Длинный ответ, вы не можете переместить std::packaged_task в std::function

Вот что я предлагаю в качестве решения:

std::vector<std::packaged_task<int()>> tasks;
std::packaged_task<int()> task{ [] () mutable { return 1; } };
tasks.emplace_back( std::move(task) );

Если вам действительно нужна функция std ::, а не просто какая-либо функция, которую нужно вызывать, вам придется связать лямбду в std::function

ответил David LUC 6 J0000006Europe/Moscow 2017, 10:56:51
0

Конструктор std::function требует, чтобы переданный функциональный объект был CopyConstructible, но std::packaged_task<F> нет (для любого F). std::function выполняет стирание типа , где динамический тип не виден в статическом типе. Рассмотрим, например:

int invoke(std::function<int()> f) { return f(); }

int main()
{
    std::packaged_task<int()> p{/*etc*/};
    auto l = [] { return 5; };
    std::function<int()> f( /* either p or l */ );
    std::cout << invoke(f) << '\n';
}

Для вызова invoke необходимо скопировать f (передать по значению). Однако f можно скопировать, если он был сделан из l, но не копируемый, если он был сделан из p, и это не имеет ничего общего со статическим типом f. Существует три основных подхода к этой проблеме:

  • Запретить копирование std::function во время компиляции.
  • Разрешить копирование std::function во время компиляции, но выдает ошибку времени выполнения, если содержащийся тип не подлежит копированию.
  • Разрешить копирование std::function во время компиляции и требует, чтобы любой объект функции, который вы в него вставили, был копируемым.

Подход № 1 очень ограничивает то, как функции могут храниться, передаваться и совместно использоваться, и в основном запрещает общие случаи использования в пользу необычного случая использования не копируемого функционального объекта.

Подход № 2 проблематичен, потому что пользователям необходимо знать, что копирование std::function в некоторых случаях может завершиться неудачей и требует особого усердия написание своего кода. Кроме того, если для разработки требуются функции совместного использования, их, возможно, потребуется заключить в std::shared_ptr. И если они должны быть скопированы и могут быть с состоянием, это становится еще хуже.

Независимо от того, как вы смотрите на подход № 3, он стандартизирован. Но в свете вышеупомянутых проблем это также легко защитить.

На самом деле я написал шаблон класса unique_function, который использует подход № 1 для моего текущего проекта, потому что для нас Вариант использования для хранения не копируемых объектов асинхронной задачи довольно распространен, и копирование или совместное использование такой задачи не требуется.

ответил Arne Vogel 6 J0000006Europe/Moscow 2017, 14:37:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132