Как объединить использование std:: bind с std:: shared_ptr

Мне нужно сделать что-то подобное более часто:

AsyncOperation * pAsyncOperation = new AsyncOperation();
auto bindOperation = std::bind(&AsyncOperation::operator(), std::ref(*pAsyncOperation));
std::thread thread(bindOperation );
thread.join();

с AsyncOperation - любой пользовательский класс, реализующий operator() (также известный как функтор или объект функции).

Можно ли указать std::bind использовать std::shared_ptr вместо std::ref? Это предотвратит утечку памяти, без необходимости сохранять ссылку на pAsyncOperation, и автоматически удалит AsyncOperation в конце потока, что является завершением этой асинхронной задачи.

EDIT: у меня не всегда есть доступ к std:: thread, потоковая библиотека может быть boost:: thread или даже любыми другими зависимыми от платформы потоками. И, следовательно, не доступ к std:: async.

Моя основная проблема заключается в том, чтобы иметь представление о владении в std:: bind.

Ответ 1

Это работает:

struct AsyncOperation {
    void operator()()
    {
        std::cout << "AsyncOperation" << '\n';
    }
};

int main() {
  std::shared_ptr<AsyncOperation>  pAsyncOperation = std::make_shared<AsyncOperation>();
  auto bindOperation = std::bind(&AsyncOperation::operator(), pAsyncOperation);
  std::thread thread(bindOperation );
  thread.join();
}

Смотрите: http://liveworkspace.org/code/4bc81bb6c31ba7b2bdeb79ea0e02bb89

Ответ 2

Вам нужно AsyncOperation динамически выделяться? Если нет, я бы сделал это:

auto f = std::async([]{ AsyncOperation()(); });
f.wait();

иначе:

std::unique_ptr<AsyncOperation> op(new AsyncOperation);
auto f = std::async([&]{ (*op)(); });
f.wait();

Конечно, вы можете использовать std::thread, но он может обеспечить больше проблем (например, обработка исключений в другом потоке). std::bind также имеет свои проблемы, и вы, вероятно, лучше закончите с лямбдой.

Если вам действительно нужно передать право собственности на другой поток, вы также можете сделать это:

std::unique_ptr<AsyncOperation> op(new AsyncOperation);
auto f = std::async([&](std::unique_ptr<AsyncOperation> op){ (*op)(); }, std::move(op));
f.wait();

поскольку lambdas еще не поддерживают захват типа перемещения.

Я надеюсь, что это поможет.