【问题标题】:compilation error when using std::unique_ptr as value in tbb::concurrent_hash_map使用 std::unique_ptr 作为 tbb::concurrent_hash_map 中的值时出现编译错误
【发布时间】:2013-10-30 20:02:49
【问题描述】:

我正在尝试用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 可能需要复制可构造/可复制分配,而不仅仅是移动可构造/移动可分配类型。
  • @mattnewport 是的,你是对的 - 就在文档中 link - 一定错过了“Types Key 和 T 必须为 CopyConstructible 概念建模” - 谢谢

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


【解决方案1】:

根据文档tbb::concurrent_hash_map 仅通过const&amp; 接受参数,这会触发unique_ptr 的副本:

bool insert( const value_type& value );

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

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

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

另一种可能性是使用std::auto_ptr 或类似的东西。但这很危险 - 正确的副本应该到达存储桶中,因此您必须对其进行测试。

【讨论】:

  • 也许 tbb 会改变并允许bool insert( value_type&amp;&amp; value ); 有人知道吗?
  • @scmcduffee 我认为他们最终会更新到 C++11。顺便说一句,Microsot PPLconcurrent_unordered_map::insert 似乎支持右值引用。
【解决方案2】:

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

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
}

【讨论】:

  • 谢谢,但无法编译。
【解决方案3】:

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

虽然我不太愿意推荐它。

【讨论】:

    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多