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

时间:2013-10-30 20:02:50

标签: gcc c++11 clang unique-ptr tbb

我正在尝试将std::unordered_map替换为tbb::concurrent_hash_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编译为ex。)或者我错过了关于concurrent_hash_maps的内容?

3 个答案:

答案 0 :(得分:3)

根据文档tbb::concurrent_hash_map仅通过引发const&副本的unique_ptr获取参数:

bool insert( const value_type& value );

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

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

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

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

答案 1 :(得分:0)

您可以通过在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
}

答案 2 :(得分:0)

我同意我的问题的答案是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));
    }
};

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