【问题标题】:Typedef mutually referenced stl containertypedef相互引用的stl容器
【发布时间】:2014-09-10 14:23:15
【问题描述】:

我有一个std::map 和一个std::list。我希望容器中的元素具有对面容器的迭代器的类型。

我怎样才能对它们进行类型定义?

示例:

 typedef std::map<MyKeyClass, typename MyList::iterator> MyMap;
 //                                    ^ MyList not defined.
 typedef std::list<typename MyMap::iterator> MyList;

当然,将两条线颠倒是行不通的。

我也试过

 typedef std::map<MyKeyClass,
                  typename std::list<typename MyMap::iterator>::iterator> MyMap;
 typedef std::list<typename MyMap::iterator> MyList;

但这也没有用。

更新: 我需要这个的原因是通过订单的两个方面来跟踪键/值对。假设我有一个map&lt;KEY,VALUE&gt;。它是按 KEY 排序的,通过一个键找到一个值很快。但我也想在添加值时跟踪这些值。我想知道最近添加的值最少。为此,我使用列表。我需要一个迭代器从地图返回到列表的原因是擦除容器中的一个元素。当我通过一个键擦除地图中的一个元素时,我还需要擦除列表中的一个元素。我也需要相反的(删除最近最少的值)。 我发现显式使用指针(如在 cmets 中)的想法行不通,因为我实际上需要一个迭代器来擦除容器中的元素。

更新 2: 我问这个是因为我觉得我不能这样做有点奇怪。我经常使用 STL 容器作为基本数据结构(每个人都这样做)。例如,std::map 可以用作具有显式结构和指针的二叉树实现的替代方案。 STL 容器设计得很好,我没有经历过我不能使用 STL 容器来表达一些可以通过结构和指针来完成的结构。他们可能无法保证 STL 容器具有与结构和指针结构相同的属性。但是,这么简单的结构,我还是觉得有点奇怪,不能用 STL 容器来表达。

【问题讨论】:

  • 这就像struct X { Y y; }; struct Y { X x; };,不是吗?
  • 是的,但在这种情况下我们可以使用前向声明。我怎么能用我的例子来做到这一点?更新:抱歉,它不能通过前向声明来完成,因为它不是指针。我在这里使用迭代器作为指针。所以我想做的是类似于迭代器的前向声明......可能无法想到。
  • 您无法控制标准库容器的内部,因此您不能断言“它就像指针”。标准说类型必须是完整的,句号。
  • @ShuSuzuki -- 在X { Y y; }; struct Y { X x; }; 的情况下,您不能转发声明 X 或 Y -- 因为要求它们也是完整的类型。前向声明给出了只能用于指针声明的不完整类型。
  • @Kerrek 是的,我知道。我想知道这个问题是否有一些解决方法。显式使用指向容器中变量的指针可能是一种可能的解决方案。但我仍然无法确信这是我们唯一能做的事情。

标签: c++ list map stl


【解决方案1】:

您可能正在寻找一个多索引容器,如 boost.js 中的容器。它允许您通过多种键类型对地图/集进行排序和访问。

Boost bimap 是一个类似的工具,只有两个键/索引,本质上允许您通过键和值访问映射。

【讨论】:

【解决方案2】:

您尝试做的事情是不可能的,因为它创建了一个无穷无尽的递归定义。

考虑在第二个示例中第一个 typedef 中发生了什么:

typedef std::map<MyKeyClass,
    typename std::list<typename MyMap::iterator>::iterator> MyMap;

里面的MyMap会被展开,你会得到

typedef std::map<MyKeyClass,
    typename std::list<typename std::map<MyKeyClass,
        typename std::list<typename MyMap::iterator>::iterator>::iterator>::iterator> MyMap;

然后会有另一个 MyMap 在那里扩展。 现在你可以看到这是怎么回事。您应该考虑您正在尝试做什么,看看是否有更好的方法来建模您的数据结构。

【讨论】:

    【解决方案3】:

    我想知道为什么需要 ciclic 类型的唯一原因是因为映射存储对列表的引用,而列表存储对映射的引用。换句话说,您希望在地图和列表之间共享数据。使用std::shared_ptrs 的map 和std::shared_ptrs 的列表,让您可以轻松地在map 和列表之间共享元素(哪些是真实数据)。

    【讨论】:

    • 我更新了问题。是的,我想在地图和列表之间共享数据。 (在我更新的问题案例中,VALUE 是共享的。)。但我仍然想知道如何根据需要擦除容器中的元素。
    【解决方案4】:

    毕竟我写了下面的代码。它是由 g++ 编译的。

    struct ListEntry;
    typedef std::unordered_map<MyKeyClass, typename std::list<ListEntry>::iterator> KeyMap;
    struct ListEntry{
       typename KeyMap::iterator it;                                                       
    };
    typedef std::list<ListEntry> MyList;
    

    【讨论】:

      猜你喜欢
      • 2011-09-18
      • 2010-09-12
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2018-08-02
      • 1970-01-01
      相关资源
      最近更新 更多