【问题标题】:Nested std::maps嵌套的 std::maps
【发布时间】:2009-09-30 19:33:50
【问题描述】:

假设我有一个名为 NamedNestedMap 的类型

std::map<std::string, std::map<std::string, NamedNestedMap> >

在这种情况下,对的每一秒(值)与父对象的种类或类型相同。我不知道如何声明它。这将允许递归算法穿过地图的“树”。

Value 类型与父类型相同,在我需要引用它的时候,它没有完全声明。

你如何声明这样嵌套的东西......

我什至不能 typedef 第一个,所以我可以包含第二个,因为它不完整

递归会在映射中寻找一些东西,当它找到它时,递归那个对象的值。算法部分看起来很简单,声明部分是这里的障碍。我不是要迭代地图的地图,只需使用 map.find,递归并再次使用 map.find。

【问题讨论】:

  • 我不明白你的问题。
  • 我认为如果你继续沿着这条推理思路,你的编译器可能会爆炸。该类的迭代器类型是什么?

标签: c++ stl


【解决方案1】:

你必须使用指针(当然,否则递归将永远不会终止 - 你总是需要一个空映射):

struct NestedMap;
struct NestedMap : std::map<std::string, NestedMap*> {};

当然,您可能希望使用shared_ptr 或类似的东西来管理内存,而不是原始指针。

【讨论】:

  • 据我所知,继承 STL 类是一件坏事。
  • 本质上并不坏。问题是 STL 类没有虚拟析构函数,所以你不能多态地使用这样的继承类(如果你通过指向基的指针删除,你会得到错误的析构函数来执行)。只要你不尝试使用多态,就完全没问题。
  • @PavelMinaev 我知道我提问的时间已经很晚了,但无论如何在这里使用 std::vector 吗?使用 std::variant 嵌套地图时,它似乎给了我错误 no operator "[]" matches these operands
【解决方案2】:

创建一个表示节点的结构。

struct Node {
    std::map<std::string, Node *> children;
};

当然,您可以将其设为一个类并隐藏数据等。

【讨论】:

    【解决方案3】:

    我猜你想要一个深度为 n 的嵌套地图:

    template<class key_type, class val_type, int nest_depth>
    struct nest
    {
    typedef std::map<key_type, typename nest<key_type, val_type, 
                    nest_depth-1>::map_type> map_type;
    };
    
    template<class key_type, class val_type>
    struct nest<key_type, val_type, 0>
    {
        typedef std::map<key_type, val_type> map_type;
    };
    

    像这样使用它:

    nest<std::string, std::string, 2> nested_map;
    

    【讨论】:

    • 如果我正确理解了他的问题,他想要一个真正的递归数据结构(本质上是一棵树),所以n 将是+INF,可以这么说。
    • 好吧,我没想到。当他试图首先声明它时,我想到了深度 n。
    【解决方案4】:

    您不能声明递归结构。

    您可能做的最好的事情就是拥有一个指针映射图。

    【讨论】:

      【解决方案5】:

      问题是NamedNestedMap 的类型定义在其递归结构中没有终止符。 NamedNestedMap 的模板扩展将是无限的,因此无法在代码中表示它。

      【讨论】:

        【解决方案6】:

        听起来你想做这样的事情:

        class Node {
            ...
        
            std::map<std::string, Node*> children;
        }
        

        这里,每个Node在一张地图中都有一张“孩子”的地图,而这个孩子可以有孩子,以此类推。

        【讨论】:

          【解决方案7】:

          你不能按照你呈现它的方式来做,而且你可能不想这样做。 这样做的原因是映射中的对是按值存储的。 您是否希望将您的任何名称-值表复制到另一个容器中? 我会按照@strager 和 Pavel 提议的方式进行包装, 可选地使用智能指针。

          【讨论】:

            【解决方案8】:

            这似乎为我编译:

            #include <map>
            #include <string>
            
            struct RecMap
            {
                std::map<std::string, RecMap> m;
            };
            
            int main()
            {
                RecMap rec;
                rec.m["first"] = RecMap();
                rec.m["first"].m["second"] = RecMap();
            }
            

            不能 100% 确定它是否合法(例如,您能否拥有一个包含 vector&lt;X&gt; 作为成员的类 X?)。这里的递归实际上并不是无限的,因为最终您会遇到一个包含空地图的 RecMap。

            编辑:this article 讨论了这种情况。结论:未定义。对不起。

            【讨论】:

              【解决方案9】:

              我认为创建递归结构会给您带来问题。只需使用法线贴图,如下所示:

              #include <map>
              #include <string>
              
              using namespace std;
              
              int main() {
                  map<string, map<string, string> > nest;
                  nest["first"]["second"] = "Hello nest!";
                  printf("%s\n", nest["first"]["second"].c_str());
                  return 0;
              }
              

              这里是执行:

              $ g++ ./nest.cpp -o nest.out -ansi -pedantic -std=c++98
              $ ./nest.out
              Hello nest!
              $
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-05-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-03-12
                • 2015-07-25
                相关资源
                最近更新 更多