boost::multi_index_container,对容器内的 std::set 进行操作

2023-12-03

我创建了一个 boost::multi_index_container (containerSet)在容器类上并索引containerSet by std::string and std::set<int>。是否可以获得在其集合中存储特定 int 的容器?此外,是否可以获取所有在其集合内至少存储 int1 和 int2 之间的一个值的容器?

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/format.hpp>
#include <boost/lambda/core.hpp>
#include <iostream>

using boost::multi_index_container;
using namespace boost::multi_index;

class Container {
public:
    std::set<int> set;
    std::string name;

    Container(std::string name, std::set<int> set);
    ~Container();

    friend std::ostream& operator<<(std::ostream& os,const Container& c) {
        os << c.name << ", [ ";
        for (int i : c.set) {
            os << i << "  ";
        }
        os << "]";
        return os;
    }
};

Container::Container(std::string name = "noName", std::set<int> set = {}) : name{name} ,set{set} {}
Container::~Container() {}

struct setTag{};
struct nameTag{};

typedef multi_index_container<Container, indexed_by<
        ordered_unique<tag<nameTag>, BOOST_MULTI_INDEX_MEMBER(Comp, std::string, name)>,
        ordered_unique<tag<setTag>, BOOST_MULTI_INDEX_MEMBER(Comp, std::set<int>, set)>
>> ContainerSet;

//don't see how I could get the compare structs to work, because
//a) can't fullfill the strict weak odering requirements and
//b) because of the setTag ordering, not all set's get called
struct compSetRange {
        bool operator()(int x,const std::set<int> &c) const {}
        bool operator()(const std::set<int> &c, int x) const {}
};
struct compSetFind {
    bool operator()(int x,const std::set<int> &c) const {}
    bool operator()(const std::set<int> &c, int x) const {}
};

int main() {
    Container c1{"c1", {5, 6, 7, 18, 61, 77}};
    Container c2{"c2", {2, 4, 5, 21, 36, 88, 99}};
    Container c3{"c3", {2, 3, 9, 10, 65, 75, 91}};
    ContainerSet cs;
    cs.insert(c1);
    cs.insert(c2);
    cs.insert(c3);

    std::cout << "print by name (ordered)" << std::endl;
    for (auto e : cs.get<nameTag>()) {
        std::cout << e << std::endl;
    }
    std::cout << std::endl;

    std::cout << "print by set (ordered)" << std::endl;
    for (auto e : cs.get<setTag>()) {
        std::cout << e << std::endl;
    }
    std::cout << std::endl;

    typedef ContainerSet::index<setTag>::type compBySetIndex;
    //find(std::set) works but isn't useful in my case
    compBySetIndex::iterator it1 = cs.get<setTag>().find(std::set<int>{2, 4, 5, 21, 36, 88, 99});
   //TODO: find all comps with int 5 -> c1 and c2
//  compBySetIndex::iterator it1 = cs.get<setTag>().find(200, compSetFind());
    if (it1 !=cs.get<setTag>().end()) {
        std::cout << *it1 << std::endl;
    }

    //TODO: find all container with values between 70 and 80 -> c1 and c3
//  compBySetIndex::iterator it1_low = cs.get<setTag>().lower_bound(70, compSetRange());
//  compBySetIndex::iterator it1_upp = cs.get<setTag>().upper_bound(80, compSetRange());

    //.range() also not applicable

    return 0;
}

与套装:
c3 = {2, 3, 9, 10, 65, 75, 91}
c2 = {2, 4, 5, 21, 36, 88, 99}
c1 = {5, 6, 7, 18, 61, 77}
我希望能够打电话...find(5);并至少得到c2, 甚至会c1在下一次调用时。使用正确的 Compare 函数这可能是可行的,但我想不出一种方法来使 operator() 函数兼容的.
此外,之后...lower_bounds(70) and ...upper_bounds(80)我应该得到c3 and c1。由于 std::set 的顺序,这个要求似乎无法通过 boost 实现。

我错过了什么吗?提前致谢!


我知道我可以对所有容器及其集合进行线性搜索来实现我的目标,但这会抵消 multi_index_container 的性能优势。如果 boost 对于这项工作来说是错误的工具,我将不得不求助于个人class containerSet.


安德鲁非常准确地诊断了这个问题。

为了帮助您,让我在 Boost 中宣传一个广泛使用的库:Boost Interval Container。

我希望这个演示能够让您了解 Boost ICL 的用途。

Live On Coliru

#include <boost/icl/separate_interval_set.hpp>
#include <boost/icl/interval_map.hpp>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>

#include <iostream>
#include <numeric>
#include <vector>

using Set = std::set<int>;

struct io_wrap { Set const& ref; };
static std::ostream& operator<<(std::ostream& os,const io_wrap& s) { os << "[ "; for (auto i : s.ref) os << i << " "; return os << ']'; }

namespace icl = boost::icl;
namespace bmi = boost::multi_index;

struct Record {
    std::string name;
    Set set;

    Record(std::string name = "noName", Set set = {}) : name{name}, set{set} {}

    friend std::ostream& operator<<(std::ostream& os,const Record& c) { return os << c.name << ", " << io_wrap{c.set}; }
};

using Map      = icl::interval_map<int, std::set<Record const*> >;
using Interval = Map::interval_type;
using Table    = bmi::multi_index_container<
         std::reference_wrapper<Record>,
         bmi::indexed_by<
             bmi::ordered_unique<
                bmi::tag<struct byName>,
                bmi::member<Record, std::string, &Record::name>
             >
         >
     >;

auto interval_set(Set const& is) { return std::accumulate(is.begin(), is.end(), icl::interval_set<int> { } ); }
auto envelope(Record const& r)   { return hull(interval_set(r.set)); }

void insert(Map& into, Set const& is, std::set<Record const*> const& rs = {}) {
    for (auto i : interval_set(is))
        into += Map::value_type { i, rs };
}

int main() {

    ////////////////////////////////
    // Prepare data
    std::vector<Record> backing_storage {
        {"c3", {2, 3, 9, 10, 65, 75, 91}},
        {"c1", {5, 6, 7, 18, 61, 77}},
        {"c2", {2, 4, 5, 21, 36, 88, 99}},
        // outliers
        {"c4", {0}},
        {"c5", {200}},
    };

    Table const byname(backing_storage.begin(), backing_storage.end());
    Map cs;
    for (auto& r : backing_storage) 
        insert(cs, r.set, { &r });

    ////////////////////////////////
    // Usage demos
    std::cout << "print by name (ordered)\n";
    for (auto const& e : byname) { std::cout << " - " << e << " - envelope: " << envelope(e) << "\n"; }
    std::cout << "\n";

    auto perform_match = [&cs](auto key) {
        Map::codomain_type matches;
        Map::codomain_combine combine;

        for (auto p : cs & key)
            combine(matches, p.second);

        std::cout << "matching " << key << ":\n";
        for (auto const* r : matches)
            std::cout << " - " << *r << "\n";
        std::cout << "\n";
    };

    for (auto key : { Set{2}, {99}, {2,99}, {2,99,5} }) {
        perform_match(interval_set(key));
    }

    perform_match(Interval::right_open(70, 81));
}

Prints:

print by name (ordered)
 - c1, [ 5 6 7 18 61 77 ] - envelope: [5,77]
 - c2, [ 2 4 5 21 36 88 99 ] - envelope: [2,99]
 - c3, [ 2 3 9 10 65 75 91 ] - envelope: [2,91]
 - c4, [ 0 ] - envelope: [0,0]
 - c5, [ 200 ] - envelope: [200,200]

matching {[2,2]}:
 - c3, [ 2 3 9 10 65 75 91 ]
 - c2, [ 2 4 5 21 36 88 99 ]

matching {[99,99]}:
 - c2, [ 2 4 5 21 36 88 99 ]

matching {[2,2][99,99]}:
 - c3, [ 2 3 9 10 65 75 91 ]
 - c2, [ 2 4 5 21 36 88 99 ]

matching {[2,2][5,5][99,99]}:
 - c3, [ 2 3 9 10 65 75 91 ]
 - c1, [ 5 6 7 18 61 77 ]
 - c2, [ 2 4 5 21 36 88 99 ]

matching [70,81):
 - c3, [ 2 3 9 10 65 75 91 ]
 - c1, [ 5 6 7 18 61 77 ]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

boost::multi_index_container,对容器内的 std::set 进行操作 的相关文章

随机推荐

  • 当 RecyclerView 正在计算布局或尝试从 recyclerview 中删除项目时滚动时,无法调用此方法

    我正在尝试从 recyclerview 中删除我的项目 但我总是收到错误 java lang IllegalStateException 无法调用此方法 RecyclerView 正在计算布局或滚动 我正在使用notify datasetc
  • DataTable Wrapper 或如何将 UI 与业务逻辑解耦

    我正在使用 Web 表单 C Asp net 众所周知 在这个模型中 UI和业务逻辑经常是混合在一起的 如何有效地将它们分开呢 我想使用的例子是 我有一个 GridView 和一个 DataTable GridView 绑定到 DataTa
  • 引用类型作为参数

    所以我深入阅读 Jon Skeet 的 C 并遇到了一些误解 比如引用类型总是通过 ref 传递 所以我决定自己做一个小实验 正如您在下面的代码中看到的 我有一个简单的 Car 类 其中一个属性在调用构造函数时初始化为 500 我还有 Nu
  • 在多个图中添加单独的箭头

    我想在用 ggplot 和 faceting 生成的 2 个图中添加箭头 问题 如何避免两个图中的箭头重复 我想为每个图添加单独的箭头 这是一个例子 library ggplot2 data frame with fake data xdf
  • Ruby 三元运算符结构

    puts bool true false 是正确的 但是 bool puts true puts false 不是 有人可以向我解释这是为什么吗 边注 bool puts true puts false 效果也很好 当您不在方法调用上添加括
  • Rails:如何将 i18n 与 Rails 4 枚举一起使用

    Rails 4 活动记录枚举很棒 但是使用 i18n 进行翻译的正确模式是什么 从Rails 5开始 所有模型都将继承自ApplicationRecord class User lt ApplicationRecord enum statu
  • SVG 未在 Windows Phone 8 Phonegap 应用程序中显示

    似乎无法找到任何答案 使用 Phonegap 并使用 SVG 图像开发 HTML5 应用程序 从 Adob e Illustrator 的 另存为 中保存它们 然后像 HTML 中的普通图像一样使用它们 img src img the im
  • 组合框中的热跟踪列表项选择

    我有一个组合框 当用户仅通过鼠标悬停来更改选择时 我需要拦截选择的更改without点击 这是为了显示有关用户将鼠标悬停在其上的项目的补充信息 CBN SELCHANGE不会完成这项工作 因为只有当用户有actually通过单击组合框项目之
  • git stash pop 和 git stash apply 之间的区别

    我一直在使用git stash pop很长一段时间 我最近了解到git stash apply命令 当我尝试它时 它的工作原理似乎与git stash pop 有什么区别git stash pop and git stash apply g
  • 快速识别用户在编辑 NSTextField 时是否按下了箭头键

    我有很多 NSTextField 我想知道用户在编辑其中之一时是否按下了方向键之一 功能 override func keyDown theEvent NSEvent switch theEvent character case NSRig
  • 如何使用 AndEngine 通过滑动来投掷/投掷球?

    我在屏幕上有一个球精灵 当我触摸并滑动该精灵时 它必须沿特定的滑动方向移动 我给那个球添加了物理原理 我想做类似的事情扔纸 谁能帮我吗 提前致谢 您需要重写 Sprite 的 onAreaTouched 方法 如下所示 您可以从 pScen
  • 条件面板上的动画

    我想在我的条件面板上添加一些动画 我找到了这里提供的解决方案 闪亮条件面板的动画 过渡 我真的很喜欢这个解决方案 但我有一个问题 检查以下示例 library shiny library shinyjs library shinydashb
  • 如何获取当前日期或/和时间(以秒为单位)

    如何使用 Javascript 获取当前日期或 和时间 以秒为单位 var seconds new Date getTime 1000 将为您提供自 1970 年 1 月 1 日午夜以来的秒数 参考
  • Apache2、PHP:创建自动ntlm登录页面

    我有 Apache2 和 PyAuthenNTLM2 模块 请参阅https github com Legrandin PyAuthenNTLM2 该 Apache 模块将 Windows 用户名放入 SERVER REMOTE USER
  • Outlook.com HTML 电子邮件中条件注释的可靠解决方案

    我在这里和其他地方看到了设置条件评论以与 Outlook com 一起使用的推荐方法 但由于下面详细介绍的另一个已知问题 我收到了空白电子邮件 参考下面的两个代码示例 我想看看是否有人有解决此问题的可靠方法 第一个例子 上面的代码会导致 O
  • Python 字节字符串在字典中打印不正确

    考虑一个列表包含字节数据 即 x03 x00 x32 temp b for c in field data temp c print x ord c 上面的代码正确地将所有字节连接到 temp 字节字符串文字 中 但是当我将其添加到字典元素
  • 点点参数的范围

    我对点 点 点参数的范围有疑问 考虑以下函数 foo foo lt function x require classInt intvl classIntervals x return intvl 该函数非常适合以下调用 x runif 10
  • Java File.renameTo(File) 不起作用

    我正在尝试列出目录的内容 并重命名某些文件 public void run String dirName try File parDir new File dirName File dirContents parDir listFiles
  • 为什么我能够在 Linux 内核模块内执行浮点运算?

    我在 x86 CentOS 6 3 内核 v2 6 32 系统上运行 我将以下函数编译到一个简单的字符驱动程序模块中作为实验 以了解 Linux 内核对浮点运算的反应 static unsigned floatstuff void floa
  • boost::multi_index_container,对容器内的 std::set 进行操作

    我创建了一个 boost multi index container containerSet 在容器类上并索引containerSet by std string and std set