【问题标题】:Merge two boost intrusive sets in C++?在 C++ 中合并两个增强侵入集?
【发布时间】:2015-07-15 15:56:13
【问题描述】:

我有两个增强侵入集,我需要将它们合并在一起。我有map_old.m_old_attributes boost 侵入集,我需要将它合并到m_map_new_attributes boost 侵入集

void DataTest::merge_set(DataMap& map_old)
{

    // merge map_old.m_old_attributes set into m_map_new_attributes
}

最好的方法是什么?我找不到可以为我进行合并的功能?我最近开始使用 boost 侵入集,但我找不到可以进行合并的预定义方法,还是我错了?

【问题讨论】:

  • 你不能用std::merge吗?
  • 我认为 boost 侵入集与 std::set 不同?
  • 如果您的代码中甚至只有一个容器,它会更加有用。我们可以想出无数种不同的方式来管理侵入性容器元素的生命周期和所有权,而且我们不太可能意外地击中您的配置。
  • @sehe 我听不懂你说什么?我还应该在代码中提供什么可以帮助你们理解的其他内容吗?
  • 理解不是问题(我已经回答了,注意了吗?)。您可能需要更具体的帮助这一事实是您需要显示更具体的代码的原因。 (展示您的侵入性元素/容器。展示您的生命周期管理。展示您的预期结果。请参阅我的答案,了解如何使用正确的预期结果断言 a SSCCE

标签: c++ boost set intrusive-containers boost-intrusive


【解决方案1】:

确实,侵入式集合是另一种野兽。他们不管理他们的元素分配。

所以在合并时你需要确定意味着什么。我想说一个合理的解释是您希望将map_old 容器中包含的元素移动到DataMap 中。

这将使map_old 为空。这是这样一个算法:

template <typename Set>
void merge_into(Set& s, Set& into) {
    std::vector<std::reference_wrapper<Element> > tmp(s.begin(), s.end());
    s.clear(); // important! unlinks the existing hooks
    into.insert(tmp.begin(), tmp.end());
}

更新 或者,您可以使用稍微复杂的迭代器擦除循环(注意迭代变异容器)以 O(1) 的内存复杂度来实现:Live On Coliru as well

    for (auto it = s.begin(); it != s.end();) {
        auto& e = *it;
        it = s.erase(it);
        into.insert(e);
    }

Live On Coliru

#include <boost/intrusive/set.hpp>
#include <boost/intrusive/set_hook.hpp>
#include <string>
#include <vector>
#include <functional>
#include <iostream>

namespace bive = boost::intrusive;

struct Element : bive::set_base_hook<> {
    std::string data;

    Element(std::string const& data = "") : data(data) {}

    bool operator< (Element const& rhs) const  { return data < rhs.data; }
    bool operator==(Element const& rhs) const  { return data ==rhs.data; }
};

using Set = bive::set<Element>;

template <typename Set>
void merge_into(Set& s, Set& into) {
    std::vector<std::reference_wrapper<Element> > tmp(s.begin(), s.end());
    s.clear(); // important! unlinks the existing hooks
    into.insert(tmp.begin(), tmp.end());
}

int main() {
    std::vector<Element> va {{"one"},{"two"},{"three"},{"four"},{"five"},{"six"},{"seven"},{"eight"},{"nine"} };
    Set a;
    for(auto& v : va) a.insert(v);

    std::vector<Element> vb {{"two"},{"four"},{"six"},{"eight"},{"ten"} };
    Set b;
    for(auto& v : vb) b.insert(v);

    assert(9==a.size());
    assert(5==b.size());

    merge_into(a, b);

    assert(a.empty());
    assert(10==b.size());
}

当然,您可以为合并操作提出不同的语义(这将更类似于“复制”而不是“移动”)

【讨论】:

  • 使用迭代器循环添加了一个更简单的版本。
猜你喜欢
  • 2013-12-17
  • 2023-03-09
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 2019-01-28
  • 1970-01-01
相关资源
最近更新 更多