使用 std::unique_ptr 作为 tbb::concurrent_hash_map 中的值时出现编译错误



我正在尝试用tbb::concurrent_hash_map替换std::unordered_map

我的原始代码:

typedef std::unique_ptr<V> V_ptr;
std::unordered_map<K, V_ptr> hm;
V_ptr v (new V);
K k;
hm.insert (std::make_pair (k, std::move (v)));

使用 clang 3.3 编译良好。 将unordered_map切换到concurrent_hash_map:

typedef std::unique_ptr<V> V_ptr;
tbb::concurrent_hash_map<K, V_ptr> hm;
V_ptr v (new V);
K k;
hm.insert (std::make_pair (k, std::move (v)));

导致错误:...stl_pair.h:105:21: error: call to deleted constructor of 'std::unique_ptr<...

这是 clang 3.3 中的错误吗? 我记得在许多容器中使用 std::unique_ptrs 时,gcc 4.5 中也有类似的错误。 (上面的原始代码不会使用 gcc 4.5 编译,例如。 或者也许我错过了关于concurrent_hash_maps的一些东西?

根据文档tbb::concurrent_hash_map仅通过触发unique_ptr副本的const&进行参数:

bool insert( const value_type& value );

作为解决方法,您可以使用std::shared_ptr或将unique_ptr存储在独立向量中:

std::vector<std::unique_ptr<V>> ptrs;

并将原始指针存储在concurrent_hash_map中。但是,对于您的用例(例如频繁删除),这可能是不可接受的。

另一种可能性是使用std::auto_ptr或类似的东西。但这很危险 - 正确的副本应该到达存储桶,所以你必须测试它。

也许您可以通过在 tbb::concurrent_hash_map 中使用更复杂的插入形式来解决此限制。以下代码片段未经测试,但先验地我认为它没有理由不起作用:

typedef std::unique_ptr<V> V_ptr;
tbb::concurrent_hash_map<K, V_ptr> hm;
V_ptr v (new V);
K k;
{ // this scope controls lifetime of the accessor
    tbb::concurrent_hash_map::accessor a;
    hm.insert (a, k);          // insert or find the key
    a->second = std::move(v);  // assign the value
}

我同意我的问题的答案是 tbb 还不支持 std::move。 我现在将坚持使用shared_ptr,但以下解决方法确实有效:

struct V_ptr : public std::unique_ptr<V> {
    typedef std::unique_ptr<V> uvptr;
    using uvptr::uvptr;
    V_ptr () : std::unique_ptr<V> () {};
    V_ptr (const V_ptr& rhs) {
        this->swap (const_cast<V_ptr&> (rhs));
    }
};

虽然我对推荐它犹豫不决。

最新更新