我正在尝试用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));
}
};
虽然我对推荐它犹豫不决。