首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >表示包含交叉引用的数据结构的STL方法

表示包含交叉引用的数据结构的STL方法
EN

Stack Overflow用户
提问于 2016-05-13 18:44:18
回答 3查看 295关注 0票数 4

我经常面对以下情况。(在不失去通用性的情况下:我在下面的示例中使用了两个容器的最简单的情况,但在几何算法的实现中,需要大量的几何算法来描述相互关联的图形数据结构。)

我有两个数据类型( AB )的大量值,它们相互引用(一般不是一对一),例如,首先通过(本机)指针或引用。它们都被放置在容器using CA = std::container1< A >;using CB = std::container2< B >;中。某些函数的结果是一对CACB实例。有一个CA实例元素,我希望删除CB实例中的引用元素,反之亦然。

代码语言:javascript
运行
复制
struct A;
struct B;

using CA = std::container1< A >;
using CB = std::container2< B >;

我想将AB定义为:

代码语言:javascript
运行
复制
struct A
{
    int payload;
    typename CB::iterator pb; // hard error here in general case of choosing `std:container2`
};

struct B
{
    double payload;
    typename CA::iterator pa;
};

// ...
PA a;
PB b;
// ...
assert(!a.empty());
assert(a.begin()->pb != b.end()); // and pb is not default-constructed
b.erase(a.begin()->pb);

活的例子。

但是目前我无法在一般情况下声明typename CB::iterator pb;,只有B /*const*/ * pb;B /*const*/ & pb;,因为作为CB声明的一部分的B类型在使用容器CB的成员typedef iterator定义聚合A时是不完整的。

有一个不完整类型的容器的建议,但它目前并不是标准的一部分。

对于当前在libstdc++和libc++中实现非调试版本的容器,上面的代码可能会很好地编译,但这一点也不是强制性的。在成功的情况下,迭代器的定义不包含任何内容,只包含指针或对value_type的引用。但在标准中没有这方面的要求。

正如您在实例化中看到的,std::unordered_set存在严重错误,因为它的迭代器要求std::hash of value_type必须是完整类型。

由于体系结构(OOP)和性能方面的原因,双重间接提出的注释可能不是很好的解决方案。至少,定义std::container3< B * >std::container2< B >以及跟踪不同交叉参照容器的动物园的有效性看起来很难看。

迭代器本质上具有指针语义。它们不应该要求引用类型的完整性。

如何处理C++14和以前的问题?

EN

回答 3

Stack Overflow用户

发布于 2016-05-13 19:40:46

我用vectorlistdequesetunordered_set尝试了第二个例子。只有对于unordered_set,我才得到一个编译器错误,可以通过使用指针容器来修复:

代码语言:javascript
运行
复制
 using CA = std::unordered_set< A* >;
 using CB = std::unordered_set< B* >;

这里 (Ideone.com C++14)。

票数 2
EN

Stack Overflow用户

发布于 2016-05-15 16:59:21

一个疯狂的解决方案是存储对齐存储,并手动管理迭代器的对象生存期,静态断言使存储达到合适的大小。

这是一个真正的痛苦和相当不安全(容易出错),但它的工作。

使用钻孔容器迭代器的大小/对齐方式。通过adl使用空闲函数访问迭代器。

std倾向于过度要求完全定义的类型。

仔细使用crtp和标记可能会让您自动化危险的代码,但很棘手。

票数 1
EN

Stack Overflow用户

发布于 2016-05-14 01:27:02

在您的实际示例中,基本上您拥有的是:具有1:1关系的intdouble,In存储在vector<int>中,双字节存储在unordered_set<double>中。

一种方法可能是简化问题,例如,您能够将数据放入unordered_map<double, int>中吗?有时,这可能是真的,并将解决许多努力。有时,这可能不是真的,例如,您可能需要按ints对数据进行排序。

我认为使用std 2容器的路径充满了困难,编译错误只是冰山一角,例如:

  • 对于1:1的关系,当您将一个条目添加到两个容器中时,您可能需要在插入一个容器时处理这个情况,但是另一个容器失败了。
  • 迭代器可能会失效(例如,如果您有一个到向量元素的迭代器,并且对该向量进行排序)
  • unordered_sets中的值(以及映射中的unordered_keys )是const (因此在添加它们之后不能更改它们)

另一个途径可以是:考虑使用类似boost、bimap或multi_index之类的东西。它们利用了这样一个事实:如果您希望两个基于节点的结构(例如两个集合)具有1:1的关系,那么对于insert,它只需要进行一个包含两个节点的分配。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37217251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档