如何将不可复制的std :: function存储到容器中?

时间:2015-01-29 07:15:05

标签: c++ function c++11 move

我想在C ++ 11中的向量或其他容器中存储回调。

这样做的一种方法是存储std :: function的向量。 这适用于带有可复制参数的lambda或std :: bind。

但是,如果存在一个不可复制(仅可移动)的参数,则由于从lambda / std :: bind内部类型到std :: function的转换而失败...

#include <vector>

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

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

    NonCopyable tmp;
    callbacks.emplace_back(std::bind([](const NonCopyable &) {}, std::move(tmp)));
    // When converting the object returned by std::bind to a std::function,
    // a copy of the arguments happen so this code cannot compile.
    return 0;
}

有没有办法将std :: bind参数移动到std :: function而不是复制它们?

2 个答案:

答案 0 :(得分:5)

在这种情况下,

std::refstd::cref用于避免复制对象(请参阅http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper)。

不确定我的问题是否正确,但这会为我编译:

#include <vector>
#include <functional>

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

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

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

    return 0;
}

编辑:如评论中所述,请注意引用变量的生命周期!

答案 1 :(得分:0)

您可以使用std::shared_ptr,这是可复制的。像

这样的东西
using ptr = std::shared_ptr<NonCopyable>;
callbacks.emplace_back(std::bind([](const ptr &) {}, ptr(new NonCopyable())));

这样NonCopyable对象将在回调析构函数上自动销毁。