Хранение не копируемого, но подвижного объекта в std::function

#c

#c

Вопрос:

Предположим, у меня есть функтор s, который не копируется, но перемещается, как я могу сохранить его в std::function? т.е. как выполнить компиляцию следующего кода? (с использованием gcc 4.6)

 #include <functional>
#include <iostream>

struct S
{
  S() = defau<
  S(S constamp;) = delete;
  Samp; operator=(S constamp;) = delete;
  S(Samp;amp;) { }
  void operator()() { }
};

std::function<void()> func;

void make_func()
{
  S s;
  func = std::bind(std::move(s));  // This won't compile
}

int main()
{
  make_func();
}
 

Комментарии:

1. это не сработает, потому s что является локальным и выходит за рамки…

2. std::function<> не содержит вызываемого объекта, который он переносит (я бы предположил, что именно для того, чтобы не требовать, чтобы они были перемещаемыми / копируемыми мной).

3.Это возможно, если вы перепроектируете свой код и сможете инициализировать std::function . Например, это работает S s; std::function<void()> func(std::ref(s)); func(); . Но вы также должны сделать s так, чтобы не выходить из области видимости раньше func , что означает, что он должен быть глобальным в некотором смысле. Но все же вы можете сохранить подвижный объект в std::function (с ограничениями), если это ваш вопрос.

Ответ №1:

Насколько я понимаю стандарт, std::function предполагается, что он может быть скопирован. Поэтому вы не можете напрямую достичь того, чего хотите.

Я бы предположил, что вам может сойти с рук какая-то пользовательская оболочка. Это будет выглядеть примерно так:

  • сделайте так, чтобы ваша оболочка содержала std::shared_ptr фактический функтор;
  • когда оболочка создается из функтора rvalue, переместите функтор в динамически выделяемую память;
  • конструктор копирования для оболочки и деструктора просто обрабатывается shared_ptr copy-ctor / destructor;
  • operator() ибо оболочка разыменовывает интеллектуальный указатель на реальный функтор и делегирует operator() его на него.

Комментарии:

1. Упражнение для читателя? Реализуйте это в общем виде, используя шаблоны переменных и совершенную пересылку типов аргументов.

2. Спасибо doublep, это отвечает моим текущим потребностям.