9 Stimmen

Wie speichert man eine nicht kopierbare std::function in einem Container?

Ich möchte Callbacks in einem Vektor oder einem anderen Container in C++11 speichern.

Ein Weg, dies zu tun, wäre ein Vektor von std::function zu speichern. Das funktioniert gut für Lambda oder std::bind mit kopierbaren Argumenten.

Wenn jedoch ein nicht kopierbares (nur verschiebbares) Argument vorhanden ist, schlägt es fehl aufgrund der Konvertierung vom internen Typ des Lambda/std::bind zu std::function...

#include 

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable &) = delete;
    NonCopyable(NonCopyable &&) = default;
};

int main() {
    std::vector> callbacks;
    callbacks.emplace_back([] {});

    NonCopyable tmp;
    callbacks.emplace_back(std::bind([](const NonCopyable &) {}, std::move(tmp)));
    // Beim Konvertieren des von std::bind zurückgegebenen Objekts zu einer std::function
    // geschieht eine Kopie der Argumente, daher kann dieser Code nicht kompiliert werden.
    return 0;
}

Gibt es einen Weg, die std::bind-Argumente in die std::function zu verschieben anstatt sie zu kopieren?

6voto

baol Punkte 4236

std::ref und std::cref sind dafür gedacht, in diesen Fällen verwendet zu werden, um das Kopieren des Objekts zu vermeiden (siehe http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper).

Ich bin mir nicht sicher, ob ich deine Frage richtig verstanden habe, aber das kompiliert für mich:

#include 
#include 

class NonCopyable {
public:
  NonCopyable() = default;
  NonCopyable(const NonCopyable &) = delete;
  NonCopyable(NonCopyable &&) = default;
};

int main() {
    std::vector> callbacks;
    callbacks.emplace_back([] {});

    NonCopyable tmp;
    auto fun = std::bind([](const NonCopyable &) {}, std::cref(tmp));
    callbacks.emplace_back(fun);

    return 0;
}

BEARBEITEN: Wie in den Kommentaren erwähnt, achten Sie auf den Lebenszyklus der referenzierten Variable!

1voto

Vladimir Talybin Punkte 514

Sie könnten std::shared_ptr verwenden, das kopierbar ist. Etwas wie

using ptr = std::shared_ptr;
callbacks.emplace_back(std::bind([](const ptr &) {}, ptr(new NonCopyable())));

Auf diese Weise wird das NonCopyable-Objekt automatisch im Destruktor von callbacks zerstört.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X