简体   繁体   English

我可以使用地图的迭代器类型作为其映射类型吗?

[英]Can I use a map's iterator type as its mapped type?

I have a tree whose nodes are large strings.我有一棵树,其节点是大字符串。 I don't really need to navigate the tree other than to follow the path from a node back to the root, so it suffices for each node to consist of the string and a pointer to its parent.除了沿着从节点返回到根的路径之外,我真的不需要在树中导航,因此每个节点都包含字符串和指向其父节点的指针就足够了。 I also need to be able to quickly find strings in the tree.我还需要能够在树中快速找到字符串。 The nodes of the tree themselves are not ordered, so this would require some sort of index.树的节点本身没有排序,因此这需要某种索引。 However, the strings are big enough that I would rather not duplicate them by storing them both in my tree and in my index.但是,这些字符串足够大,我不想通过将它们同时存储在我的树和索引中来复制它们。

I could implement both my tree and the index with a single std::map if the key for the map was the string and the mapped value was the pointer to its parent.如果 map 的键是字符串并且映射值是指向其父项的指针,我可以使用单个 std::map 实现我的树和索引。 However, I cannot figure out a way to write either of these types.但是,我想不出一种方法来编写这些类型中的任何一种。 My best guess would be something like this:我最好的猜测是这样的:

using Tree = std::map<std::string, typename Tree::const_iterator>;

or maybe:或者可能:

using Node = std::pair<std::string const, typename Node const*>;
using Tree = std::map<std::string, Node const*>;

But these recursive type definitions don't compile.但是这些递归类型定义无法编译。 Is there any way to create this type in C++?有没有办法在 C++ 中创建这种类型? Or a better way to do what I am trying to do?或者更好的方法来做我想做的事情?

You can wrap the iterator in a type of your own and reference that type instead to avoid the recurisve type problem.您可以将迭代器包装在您自己的类型中并引用该类型来避免递归类型问题。

struct const_iterator_wrapper {
    using iterator_type = map<string, const_iterator_wrapper>::const_iterator;

    iterator_type iter;

    const_iterator_wrapper() {}
    const_iterator_wrapper(iterator_type _iter) : iter(_iter) {}
};

using tree = map<string, const_iterator_wrapper>;

Your using Node definition doesn't compile, but an actual structure would:using Node定义无法编译,但实际结构会:

struct Node {
    std::string const s;
    Node const* n;
};

It was not mentioned whether or not a node's parent might change after creation.没有提到节点的父节点在创建后是否会发生变化。 If it does not, then a set might be a better fit than a map .如果不是,那么set可能比map更合适。 (If it does change, then the set option is not completely off the table, but it might require weakening const correctness guarantees, possibly by making the parent pointer mutable .) In fact, you might not have to change your data structure much to use a set . (如果它确实改变了,那么set选项并没有完全脱离表格,但它可能需要削弱const正确性保证,可能是通过使父指针mutable 。)事实上,你可能不必改变你的数据结构就可以使用set

Let's say your nodes currently look like the following.假设您的节点当前如下所示。

struct Node {
    std::string data;
    const Node * parent; // Might need to add `const`
};

You want these sorted by the data, ignoring the parent pointer.您希望这些按数据排序,忽略父指针。 This might require defining a new function. If the following operator< is already defined as something else, then it takes a little more work to define your set , but still not hard.这可能需要定义一个新的 function。如果下面的operator<已经被定义为其他东西,那么定义你的set需要更多的工作,但仍然不难。

bool operator<(const Node &a, const Node &b) {
    return a.data < b.data;
}

This is all you need to define a set of these nodes that will function much like your desired map.这就是定义一组这些节点所需的全部内容,这些节点将 function 与您想要的 map 非常相似。

std::set<Node> tree;

// Add a root element.
auto result = tree.emplace("root", nullptr);
auto root_it = result.first;

// Add a child to the root.
tree.emplace("child", &*root_it);
// The `&*` combination may look odd. It is, though, a way to
// convert an iterator to a pointer.

There are a few gotchas that some people might find unexpected, but nothing other than what comes from using a map for this role.有些人可能会发现一些意想不到的陷阱,但除了使用map作为此角色之外,别无其他。

In the end, as far as the structure of the data is concerned, a map<K, const V> is equivalent to a set<pair<K, V>> with a suitable comparison function. While the member functions differ, the biggest real functional difference between a map and a set of pairs is that the map's values can be changed (hence const V instead of V earlier).最后,就数据的结构而言, map<K, const V>等价于set<pair<K, V>>比较合适 function。虽然成员函数不同,但最大的map 和一组对之间的真正功能差异在于地图的值可以更改(因此const V而不是之前的V )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM